copy
官方的里子:https://gpdb.docs.pivotal.io/6-8/ref_guide/sql_commands/COPY.html
能导入到stdin、stdout中,也能导出到具体的文件中。
普通导入
导出
copy table to '/tmp/table.csv';
copy (select * from table where ... group by ... order by ...) to '/tmp/table.csv';
导入
copy table to '/tmp/table.csv';
例子
ON SEGMENT
这个命令是加强命令,很适合多个机器之间传数据。
导出到csv文件
具体执行的命令
COPY tu_doc_info TO PROGRAM 'cat > /tmp/tu_doc_info<SEGID>.csv' ON SEGMENT CSV;
COPY tu_doc_info TO '/tmp/tu2<SEGID>.csv' ON SEGMENT CSV;
以上两种方式,都尝试过了,两次导出的文件。还不一样。每个SEGID文件记录数还不太一样。
上述SEGID变量,gp会识别,并转换成具体的序列好。
csv文件到gp
COPY tu_doc_info FROM '/tmp/tu2<SEGID>.csv' ON SEGMENT CSV;
尝试直接加载未经处理的数据:
COPY tu_doc_info FROM '/path/20200701/tu_doc_info_20200701<SEGID>0500.csv' ON SEGMENT CSV;
错误信息:
ERROR: value of distribution key doesn't belong to segment with ID 11, it belongs to segment with ID 14 (seg11 10.181.86.12:55011 pid=54103)
CONTEXT: COPY tu_doc_info, line 1:
总结: 它说 你把别的分区的数据给我了 。
所以,这个应该是同等数目的节点 升级 、保存之类的
忽略错误
对于一个csv文件,如果存在乱码,或者导入的csv文件中的字段过长,无法导入,其特性是,整体导入成功,或者整体导入失败。这个特性很好,如果发现出错了,我们可以重新再导致那个文件。
但是,它也能忽略错误,并记录到日志中。测试发现,确实能实现。
copy mytable from '$filename' with csv LOG ERRORS SEGMENT REJECT LIMIT 10 ROWS;
-- 或者百分比 PERCENT
上面能达到,即使出错了,未达到它的容忍度的时候,依然能导入成功数据。
SEGMENT REJECT LIMIT 10 ROWS; 是指节点超过这个度吗?还是说整体?
查看错误日志
SELECT * from gp_read_error_log('table');清空日志
SELECT gp_truncate_error_log('table');然后再从错误日志中恢复到记录中。
PROGRAM
该关键字能调用shell命令调用shell
-- 以前无法解决的乱码问题,下面命令直接解决了。
COPY tu_doc_info FROM PROGRAM 'iconv -f UTF-8 -t UTF-8 /etl/dta/20200701/tu_doc_info_20200701010500.csv' CSV;
-- 前面的命令
COPY tu_doc_info TO PROGRAM 'cat > /tmp/tu_doc_info<SEGID>.csv' ON SEGMENT CSV;
COPY LINEITEM_4 FROM PROGRAM 'cat /tmp/lineitem_program<SEGID>.csv' ON SEGMENT CSV;
这个应该类似于管道命令符号一样。它能和linux系统里面的管道符号结合在一起。
分组统计,如何能将一次查询的结果,按照不同的分组(如省,或时间)分组到不同的文件中?难到要自己写shell?
copy来导入数据
利用stdin、stdout在两个数据库之间,传递数据。
https://blog.csdn.net/weixin_39540651/article/details/115494761
!/bin/bash
psql \
-X \
-U user_name \
-h host_name1 \
-d database_name \
-c "\\copy tbl_students to stdout" \
| \
psql \
-X \
-U user_name \
-h host_name2 \
-d database_name \
-c "\\copy tbl_students from stdin"
如,保存为copy_data.sh,则执行的时候,执行sh copy_data.sh。
copy导出数据到多个文件
比如,分组。如果分组不太多的话,则写多个copy的命令,但是,为每个分组,都要写一个where条件,这个条件,可能要重复计算。(为了减少where时的全表扫描,则,可以建立一个分组表,然后,每次一个分组,即可。)(那么,如何根据多种条件,来建立分组呢?比如范围、或者其他)
另外,如果将产生的数据输出到STDOUT,然后,在shell里面读入数据,然后决定写入到不同的文件,理论上应该也是行的?那么,又如何操作呢?
待研究。