业务方要求将pg中的一个表导入sqlserver,表约1000万行。测试了几种常用的导入导出方法,有成功也有失败的。

 

一、 pg导出为sql文件,sqlserver中执行

如果没有用到特殊数据类型或者字符,数据量也比较小,这种方法一般是可以的。

1. pg导出

里面会有建表、建索引、授权等语句,需要处理一下,或者可以用 --data-only选项。

pg_dump -d dbname -U username -t tablename --inserts > tablename.sql

2. sqlserver导入

根据文件大小分为三种情况:

  • 10M以下:直接用SSMS打开,执行即可
  • 10~200M:这时用SSMS打开可能会很慢,或者SSMS直接崩溃,可以使用sqlcmd执行sql文件(类似sqlplus 的 @xx.sql)
#cd到文件所在目录
sqlcmd -i xxx.sql -d dbname
  • 200M以上:执行会占用大量内存,可能挤压sqlserver可用内存,影响业务,不推荐使用该方法。

在测试环境执行的时候2G的sql文件执行占用内存超过15G(并且还在往上涨)

pg导入数据至sqlserver方法整理及对比_sql

 

二、 pg导出为csv文件,sqlserver用bulk insert

测试bulk insert效率很高,960万行数据执行约53秒,对内存影响也不大。

1. pg导出

psql -d dbname
\copy (select * from xxx) to '/tmp/xxx.csv' DELIMITER ',' CSV;

2. 换行符格式转换

大多数pg装在Linux,sqlserver装在windows,所以要特别注意换行符的问题,否则执行bulk insert的时候会报错第一行最后一列过长,因为它识别不到换行符,把后面的所有数据都当做第一行最后一列。

#Linux格式转windows
sed -e 's/$/\r/' 1pnet.txt >dos.txt

3. sqlserver导入

BULK INSERT 库名..表名 
FROM 'c:\test.csv' 
WITH ( 
FIELDTERMINATOR = ',', ---分隔符
ROWTERMINATOR = '\n'    ---换行符
)

 

三、 pg导出为csv文件,sqlserver导入导出向导

第一步同上,第二步使用sqlserver导入导出向导,导入类型选择“平面文件”,定义列名及类型。

但说实话导入导出向导经常会遇到奇奇怪怪的报错,而且搜不到啥好的解决方法,本次遇到报错如下

pg导入数据至sqlserver方法整理及对比_导入导出_02

根据搜到的文章说是字符集问题,但检查导入表里并没有特别字符,改换导入时选择的字符集后也无效,暂未找到解决方法

 

四、 pg导出为csv文件,sqlserver用bcp导入

第一步同上,第二步使用BCP导入

参考 

https://billtian.github.io/digoal.blog/2018/08/19/02.html