原 GreenPlum中的copy命令
Tags: 原创GreenPlum导出数据文本导出导入COPY加载数据
COPY和“\copy”的区别
psql支持文件数据导入到数据库,也支持数据库表数据导出到文件中。 COPY命令和\copy 命令都支持这两类操作,但两者有如下区别:
- COPY 命令是SQL命令,\copy 命令是元命令。
- 执行COPY 命令的用户必须具有SUPERUSER超级权限(将数据通过stdin/stdout方式导入导出情况除外)或授予了默认角色
pg_read_server_files
、pg_write_server_files
及pg_execute_server_program
之一的用户,而 \copy 元命令不需要SUPERUSER权限。 - COPY 命令读取或写入数据库服务端主机上的文件,而 \copy 元命令是从psql客户端主机读取或写入文件。
- 从性能方面看, 大数据量导出文件或大文件数据导入数据库,COPY 比 \copy 性能高。
用COPY装载数据
COPY FROM将文件或标准输入中的数据复制到表中,并将数据附加到表内容中。 COPY是非并行的:使用Greenplum master实例在单个进程中加载数据。建议仅对非常小的数据文件使用COPY。
Master主机上的postgres进程必须可以访问COPY 源文件。指定相对于Master主机上的数据目录的COPY 源文件名,或指定绝对路径。
Greenplum使用客户端和master服务器之间的连接从STDIN或STDOUT复制数据。
从文件装载
COPY 命令要求postgres后端打开指定的文件,读取文件并将其附加到表中。为了能够读取文件,后端需要具有对文件的可读权限,并且必须使用master主机上的绝对路径或master数据目录的相对路径来指定文件名。
1 | COPY table_name FROM /path/to/filename; |
从STDIN装载
为避免在加载数据之前将数据文件复制到master主机的问题,COPY FROM STDIN使用标准输入通道并将数据直接提供给postgres后端。 COPY FROM STDIN命令启动后,后端将接受数据行,直到一行只包含反斜杠句点(.)。
1 | COPY table_name FROM STDIN; |
在psql中使用\copy装载数据
不要将psql \copy命令与COPY SQL命令混淆。 \copy调用常规COPY FROM STDIN并将数据从psql客户端发送到后端。 因此,任何文件都必须驻留在运行psql客户端的主机上,并且必须可由运行客户端的用户访问。
为避免在加载数据之前将数据文件复制到master主机的问题,COPY FROM STDIN使用标准输入通道并将数据直接提供给postgres后端。 COPY FROM STDIN命令启动后,后端将接受数据行,直到一行只包含反斜杠句点(.)。psql将所有这些包装到handy \copy 命令中
1 | \copy table_name FROM filename; |
输入格式
COPY FROM接受FORMAT参数,该参数指定输入数据的格式。可能的值为TEXT,CSV(逗号分隔值)和BINARY。
1 | COPY table_name FROM /path/to/filename WITH (FORMAT csv); |
FORMAT csv将读取逗号分隔值。默认情况下,FORMAT text使用制表符来分隔值,DELIMITER选项将不同的字符指定为值分隔符。
1 | COPY table_name FROM /path/to/filename WITH (FORMAT text, DELIMITER '|'); |
默认情况下,使用默认客户端编码,可以使用ENCODING选项更改此编码。这对于来自其他操作系统的数据会非常有用。
1 | COPY table_name FROM /path/to/filename WITH (ENCODING 'latin1'); |
使用COPY卸载数据
COPY TO在Greenplum的Master主机上用一个Master实例的单进程从一个表复制数据到一个文件(或者标准输入)。使用COPY输出一个表的全部内容,或者使用一个SELECT语句过滤输出。例如:
1 2 | COPY (SELECT * FROM country WHERE country_name LIKE 'A%') TO '/home/gpadmin/a_list_countries.out'; |
在单行错误隔离模式中运行COPY
默认情况下,COPY会在第一个错误处停止操作:如果数据包含一个错误,该操作失败并且没有数据被装载。如果用户在单行错误隔离模式中运行COPY FROM,Greenplum会跳过包含格式错误的行并且装载正确格式化的行。单行错误隔离模式只适用于包含格式错误的输入文件中的行。如果数据包含的是约束错误,例如违背NOT NULL,CHECK,或者 UNIQUE约束,操作还是会失败并且不会有数据被装载。
指定SEGMENT REJECT LIMIT 会把COPY操作运行在单行错误隔离模式中。指定每一个Segment上可接受的错误行数,在达到这个行数后整个COPY FROM操作失败并且不会有数据被装载。这个错误行计数是针对每个Greenplum数据库的Segment,而不是针对整个装载操作。
如果COPY操作没有达到操作限制,Greenplum会装载所有正确格式化的行并且丢弃错误行。使用LOG ERRORS子句可以捕获Greenplum数据库内部的数据格式化错误。例如:
1 2 3 | => COPY country FROM '/data/gpdb/country_data' WITH DELIMITER '|' LOG ERRORS SEGMENT REJECT LIMIT 10 ROWS; |
有关调查错误行的信息,请见在错误日志中查看不正确的行。
在错误日志中查看不正确的行
如果用户使用了单行错误隔离(见定义一个带有单行错误隔离的外部表或者在单行错误隔离模式中运行COPY),任何由格式错误的行会被Greenplum数据库内部记录下来。
Greenplum数据库用一种表格式捕捉下列错误信息:
列 | 类型 | 描述 |
---|---|---|
cmdtime | timestamptz | 错误发生时的时间戳。 |
relname | text | COPY命令的外部表名称或者目标表名称。 |
filename | text | 包含该错误的装载文件的名称。 |
linenum | int | 如果使用的是COPY,这里是错误发生在装载文件的行号。对于使用file://协议或者gpfdist://协议以及CSV格式的外部表,文件名和行号会被记录。 |
bytenum | int | 对于使用gpfdist://协议以及TEXT格式数据的外部表:错误发生在装载文件中的字节偏移。gpfdist按块解析TEXT文件,因此不可能记录行号。CSV文件是一次解析一行,因此对于CSV文件可以跟踪行号。 |
errmsg | text | 错误消息文本。 |
rawdata | text | 被拒绝行的裸数据。 |
rawbytes | bytea | 在有数据库编码错误(使用的客户端编码不能被转换成一种服务器端编码)的情况中,不可能把编码错误记录为rawdata。相反会存储裸字节,并且用户将看到任何非七位ASCII字符的十进制码。 |
用户可以使用Greenplum数据库的内建SQL函数gp_read_error_log()来显示内部记录的格式化错误。例如,这个命令显示表ext_expenses的错误日志信息:
1 | SELECT gp_read_error_log('ext_expenses'); |
COPY命令详解
在文件和表之间复制数据。
概要
1 2 3 4 5 6 7 8 | COPY table_name [(column_name [, ...])] FROM {'filename' | PROGRAM 'command' | STDIN} [ [ WITH ] ( option [, ...] ) ] [ ON SEGMENT ] COPY { table_name [(column_name [, ...])] | (query)} TO {'filename' | PROGRAM 'command' | STDOUT} [ [ WITH ] ( option [, ...] ) ] [ ON SEGMENT ] |
其中option可以是以下之一:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | FORMAT format_name OIDS [ boolean ] FREEZE [ boolean ] DELIMITER 'delimiter_character' NULL 'null string' HEADER [ boolean ] QUOTE 'quote_character' ESCAPE 'escape_character' FORCE_QUOTE { ( column_name [, ...] ) | * } FORCE_NOT_NULL ( column_name [, ...] ) ENCODING 'encoding_name' FILL MISSING FIELDS LOG ERRORS [ SEGMENT REJECT LIMIT count [ ROWS | PERCENT ] ] IGNORE EXTERNAL PARTITIONS |
描述
COPY在Greenplum数据库表和标准文件系统文件之间移动数据。 COPY TO将表的内容复制到一个文件(如果在ON SEGMENT上复制,则将基于segment ID复制到多个文件), 而COPY FROM将数据从文件复制到表(将数据追加到表中已有的任何内容)。 COPY TO还可以复制SELECT查询的结果。
如果指定了列列表,则COPY仅将指定列中的数据复制到文件中或从文件复制。 如果表中的任何列不在列列表中,则COPY FROM将为这些列插入默认值。
带有文件名的COPY指示Greenplum数据库master主机直接从文件读取或写入文件。 该文件必须可供master主机访问,并且必须从master主机的角度指定名称。
当COPY与ON SEGMENT子句一起使用时, ON SEGMENT导致segment创建单独的面向segment的文件,这些文件保留在segment主机上。 ON SEGMENT的filename参数采用字符串文字(必需),并使用绝对路径或字符串文字。 运行COPY操作时,segment ID和segment数据目录的路径将替换为字符串文字值。
使用复制表(DISTRIBUTED REPLICATED)作为源的COPY TO将创建一个文件,其中包含来自单个segment的行,以便目标文件不包含重复的行。 将COPY TO与ON SEGMENT子句一起使用,并将复制表作为源,则在包含所有表行的segment主机上创建目标文件。
ON SEGMENT子句允许您将表数据复制到segment主机上的文件中,以用于诸如在集群之间迁移数据或执行备份之类的操作。 可以使用诸如gpfdist之类的工具来恢复由ON SEGMENT子句创建的细分数据,这对于高速数据加载非常有用。
Warning: 建议仅对专业用户使用ON SEGMENT子句。
指定PROGRAM时,服务器将执行给定命令并从程序的标准输出中读取或写入程序的标准输入。 该命令必须从服务器的角度指定,并且可由gpadmin用户执行。
当指定STDIN或STDOUT时,数据将通过客户端和master之间的连接进行传输。 STDIN和STDOUT不能与ON SEGMENT子句一起使用。
如果使用SEGMENT REJECT LIMIT,则COPY FROM操作将在单行错误隔离模式下运行。 在此版本中,单行错误隔离模式仅适用于输入文件中格式错误的行 - 例如,多余或缺失的属性,错误的数据类型的属性或无效的客户端编码序列。 约束错误(例如违反NOT NULL,CHECK或UNIQUE约束)仍将在“全有或全无”输入模式下处理。 用户可以指定可接受的错误行数(基于每个segment),之后将终止整个COPY FROM操作,并且不会加载任何行。 错误行的计数是按segment而不是整个加载操作计数的。 如果未达到每个segment拒绝的限制,那么将加载所有不包含错误的行,并丢弃所有错误行。 要保留错误行以供进一步检查,请指定LOG ERRORS子句以捕获错误日志信息。 错误信息和该行存储在Greenplum内部数据库中。
输出
成功完成后,COPY命令将返回以下形式的命令标签,其中count是复制的行数:
1 | COPY count |
如果以单行错误隔离模式运行COPY FROM命令, 如果由于格式错误而未加载任何行,则将返回以下通知消息,其中count是拒绝的行数:
1 | NOTICE: Rejected count badly formatted rows. |
参数
table_name
现有表的名称(可以由模式指定)。
column_name
要复制的列的可选列表。如果未指定列列表,则将复制表的所有列。
当以文本格式复制时,默认情况下,bytea类型的列中的一行数据最多可为256MB。
query
SELECT或VALUES命令,其结果将被复制。 请注意,查询周围需要括号。
filename
输入或输出文件的路径名。 输入文件名可以是绝对路径或相对路径,但输出文件名必须是绝对路径。 Windows用户可能需要使用E’’字符串并将路径名中使用的所有反斜杠加倍。
PROGRAM ‘command’
指定要执行的命令。 在COPY FROM中,从命令的标准输出中读取输入,而在COPY TO中,将输出写入命令的标准输入中。 必须从Greenplum数据库master主机系统的角度指定该command,并且该命令必须由Greenplum数据库管理员用户(gpadmin)执行。
该command由shell程序调用。 将参数传递给shell时,请删除或转义对shell具有特殊含义的任何特殊字符。 出于安全原因,最好使用固定的命令字符串,或者至少避免在字符串中传递任何用户输入。
当指定ON SEGMENT时,该命令必须由Greenplum数据库管理员用户(gpadmin)在所有Greenplum数据库primary segment主机上可执行。 该命令由每个Greenplum segment实例执行。 在command中是必需的。
有关命令语法要求和指定该子句时要复制的数据的信息,请参见ON SEGMENT子句。