这是本节的多页打印视图。 点击此处打印.

返回本页常规视图.

处理杂乱的数据

使用 COPY 加载数据有两个主要阶段:解析和加载。在解析过程中,如果 COPY 遇到错误,它会拒绝错误数据并继续加载数据。每当 COPY 无法解析某行数据时,便会创建拒绝数据。下面是一些可能导致拒绝行的解析器错误:

  • 解析器选项不受支持

  • 数据要加载到的表的数据类型不正确,包括集合成员的数据类型不正确

  • 所用解析器的上下文格式错误

  • 缺少分隔符

COPY 可以选择在加载阶段转换数据时拒绝数据并继续加载。此行为由配置参数控制。默认情况下,如果在加载阶段遇到错误,COPY 会中止加载。

一些可选参数可让您确定 COPY 处理拒绝的严格程度。例如,可让 COPY 在拒绝单行时就失败,也可以在加载失败前允许特定数量的拒绝。此部分介绍用于确定 COPY 如何处理被拒绝数据的参数。

保存拒绝行(REJECTED DATA 和 EXCEPTIONS)

COPY 语句自动将每个拒绝行的副本保存在 rejections 文件中。COPY 还将有关拒绝原因的相应解释保存在 exceptions 文件中。默认情况下,Vertica 将这两个文件保存在名为 CopyErrorLogs 的数据库编录子目录中,如本例中所示:

v_mart_node003_catalog\CopyErrorLogs\trans-STDIN-copy-from-rejected-data.1
v_mart_node003_catalog\CopyErrorLogs\trans-STDIN-copy-from-exceptions.1

您可以选择以其他两种方式之一保存 COPY 拒绝和异常:

  • 使用 REJECTED DATAEXCEPTIONS 选项将两个输出保存到您选择的位置。REJECTED DATA 记录拒绝的行,而 EXCEPTIONS 记录每行拒绝原因的描述。如果路径值是现有目录或以 '/' 结尾,或者加载包含多个源,则将文件写入该目录中。(如果该目录不存在,COPY 会创建该目录。)如果路径值是一个文件且写入多个文件,则 COPY 使用它作为文件前缀。

  • 使用 REJECTED DATA AS TABLE 选项。此选项将拒绝数据和异常描述写入同一个表。有关详细信息,请参阅将拒绝的数据保存到表中

如果将拒绝数据保存到表中,表文件则存储在数据子目录中。例如,在 Vmart 数据库安装中,拒绝数据表记录存储在 RejectionTableData 目录中,如下所示:

=> cd v_mart_node003_data\RejectionTableData\
=> ls
TABLE_REJECTED_RECORDS_"bg"_mytest01.example.-25441:0x6361_45035996273805099_1.1
TABLE_REJECTED_RECORDS_"bg"_mytest01.example.-25441:0x6361_45035996273805113_2.2
.
.
.
TABLE_REJECTED_RECORDS_"delimr"_mytest01.example.-5958:0x3d47_45035996273815749_1.1
TABLE_REJECTED_RECORDS_"delimr"_mytest01.example.-5958:0x3d47_45035996273815749_1.2

COPY LOCAL 拒绝数据

对于 COPY LOCAL 操作,如果您将 REJECTED DATAEXCEPTIONS 用于文件路径,则文件写入客户端。如果您希望拒绝在所有节点上可用,请使用 REJECTED DATA AS TABLE 而不是 REJECTED DATA

强制截断或拒绝行 (ENFORCELENGTH)

解析 CHAR、VARCHAR、BINARY 或 VARBINARY 数据时,行可能会超过目标表长度。默认情况下,COPY 会截断此类行,但不拒绝它们。使用 ENFORCELENGTH 选项拒绝超出目标表的行。

例如,如果将 'abc' 加载到指定为 VARCHAR(2) 的表列,COPY 则会将值截断成 'ab',然后再进行加载。使用 ENFORCELENGTH 选项加载同一行会导致 COPY 拒绝该行。

指定最大拒绝数 (REJECTMAX)

REJECTMAX 选项指定在加载失败前可以拒绝的最大逻辑记录数。拒绝行由批量加载过程中无法解析(或无法转换)成相应数据类型的数据组成。拒绝数据并不指示引用约束。有关使用约束以及在批量加载过程中强制执行约束的选项的信息,请参阅约束

当拒绝记录数等于 REJECTMAX 值时,加载将失败。如果未指定 REJECTMAX 值或该值为 0,则 COPY 允许的异常数无限制。

如果允许 COPY 在遇到转换错误时拒绝行然后继续,请考虑使用 REJECTMAX 限制影响。请参阅处理转换错误

处理转换错误

默认情况下,如果在执行转换时遇到错误,则 COPY 中止加载。这是默认设置,因为拒绝转换错误可能比拒绝解析错误成本更高。但是,有时您更愿意无论如何都加载数据并拒绝有问题的行,就像对待解析错误一样。

要让 COPY 将转换表达式中的错误视为解析错误,请将 CopyFaultTolerantExpressions 配置参数设置为 1。(请参阅常规参数。)在数据加载的表达式评估阶段,在转换期间被拒绝的行将被写入与解析期间被拒绝的行相同的目的地。使用 REJECTED DATAREJECTED DATA AS TABLE 指定输出位置。

如果数据包含一些错误行,您可能希望启用转换拒绝。通过启用这些拒绝,您可以加载大部分数据并继续。Vertica 建议在启用转换拒绝时使用 REJECTMAX

如果数据包含许多错误值,则加载非错误行的性能可能比解析器错误更差。

出现任何错误时中止数据加载 (ABORT ON ERROR)

使用 ABORT ON ERROR 选项是限制性最强的数据加载方式,因为不允许任何异常或拒绝。如果任何行遭拒,COPY 操作将停止。不会加载任何数据,而且 Vertica 回退命令。

如果您使用 ABORT ON ERROR 作为 CREATE EXTERNAL TABLE 语句的一部分,则每当查询引用外部表时都会使用该选项。违规错误保存在 COPY 异常或拒绝数据文件中。

了解行拒绝和回退错误

根据 COPY 遇到的错误类型,Vertica 将执行下列操作之一:

  • 拒绝违规行并将其他行加载到表中

  • 回退整个 COPY 语句,但不加载任何数据

COPY 无法解析包含以下任一项的行:

  • 不兼容数据类型

  • 缺失字段

  • 缺少分隔符

如果遇到以下任一条件,COPY 会回退语句:

  • 服务器端错误,如缺少内存

  • 违反主键或外键约束

  • 将 NULL 数据加载到 NOT NULL 列中

  • 转换错误(默认情况)

此示例演示当 Vertica 无法将行解析成所请求的数据类型时所发生的情况。例如,在下列 COPY 语句中,"a::INT + b::INT" 是一个 SQL 表达式,其中 ab 为衍生值:

=> CREATE TABLE t (i INT);
=> COPY t (a FILLER VARCHAR, b FILLER VARCHAR, i AS a::INT + b::INT)
   FROM STDIN;
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself.
>> cat|dog
>> \.

Vertica 无法将行解析成所请求的数据类型,因而拒绝行:

ERROR 2827:  Could not convert "cat" from column "*FILLER*".a to an int8

如果 a 解析为 'cat'b 解析为 'dog',则下一个表达式 'cat'::INT + 'dog'::INT 将返回表达式评估程序错误:

=> SELECT 'cat'::INT + 'dog'::INT;
ERROR 3681:  Invalid input syntax for integer: "cat"

下列 COPY 语句也会回退,因为 Vertica 无法将行解析成所请求的数据类型:

=> COPY t (a FILLER VARCHAR, i AS a::INT) FROM STDIN;

在下列 COPY 语句中,Vertica 仅拒绝违规行但不回退语句。COPY 将 'cat' 直接解析为 INTEGER,而不是将 'cat' 行计算为 VARCHAR 类型。

=> COPY t (a FILLER INT, i AS a) FROM STDIN;

在以下示例中,转换错误被拒绝而不是中止加载。

=> ALTER DATABASE DEFAULT SET CopyFaultTolerantExpressions = 1;
ALTER DATABASE

=> CREATE TABLE sales (price INTEGER);
CREATE TABLE

=> COPY sales (f FILLER VARCHAR, price AS f::INT)
   FROM STDIN REJECTED DATA AS TABLE sales_rej;

=> COPY sales FROM STDIN REJECTED DATA AS TABLE sales_rej;
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself.
>>1
>>2a
>>3
>>\.

=> SELECT * FROM sales;
 price
-------
     1
     3
(2 rows)

=> SELECT rejected_data, rejected_reason FROM sales_rej;
 rejected_data |                rejected_reason
---------------+-----------------------------------------------
 Tuple (2a)    | ERROR 2827:  Could not convert "2a" from column "*FILLER*".f to an int8
(1 row)

另请参阅

1 - 保存加载拒绝 (REJECTED DATA)

COPY 加载拒绝是由于解析器出现异常或者出现转换错误而未加载的数据行。默认情况下,如果您未指定包含拒绝数据的文件,则 COPY 会将包含拒绝数据的文件保存到以下位置:

catalog_dir/CopyErrorLogs/target_table-source-copy-from-rejected-data.n

将拒绝的数据保存到默认位置或所选位置,可以让您查看文件内容、解决问题以及从包含拒绝数据的文件中重新加载数据。将拒绝的数据保存到某个表中后,您可以查询该表以查看拒绝的数据行以及无法解析行的原因(异常)。Vertica 建议将拒绝的数据保存到表中。

多个包含拒绝数据的文件

除非加载非常小 (< 10 MB),否则 COPY 会创建多个文件来保存拒绝的行。决定 COPY 为拒绝的数据创建的文件数有几个因素。以下是其中一些因素:

  • 正在加载的源数

  • 拒绝的行总数

  • 源文件(或多个文件)的大小

  • 协作解析和正在使用的线程数

  • 支持分摊加载的 UDL

  • 对于您自己的 COPY 解析器,从 prepareUDSources() 返回的对象数

拒绝文件的命名约定

您可以使用正在加载的文件指定一个或多个包含拒绝数据的文件。使用 REJECTED DATA 参数指定文件位置和名称,并用逗号 (,) 分隔包含连续拒绝数据的文件名。请勿使用 ON ANY NODE 选项,因为它仅适用于加载文件。

如果指定一个或多个文件,并且 COPY 需要多个文件来存储拒绝的数据,则 COPY 使用您提供的拒绝数据文件名作为前缀,并为每个包含拒绝数据的文件附加数字后缀。例如,如果为 REJECTED_DATA 参数指定名称 my_rejects,并且您正在加载的文件足够大 (> 10 MB),则会存在如下几个文件:

  • my_rejects-1

  • my_rejects-2

  • my_rejects-3

COPY 默认使用协作解析,可让节点解析文件内容的特定部分。根据文件或部分的大小,每个线程会为每个源文件或部分至少生成一个包含拒绝数据的文件,并将加载结果返回给启动程序节点。当 COPY 使用多个线程(.1、.2、.3 等)时,文件后缀是线程索引。

要使每个线程能够解析任何部分,拒绝的最大数据文件数量不能大于正在加载的源数量。最大线程数由资源池决定。对于协作解析,请使用所有可用线程。

如果将 COPY 与支持分摊加载的 UDL 结合使用,则文件后缀是偏移量值。支持分摊加载的 UDL 使得协作解析变得没有必要。对于分摊加载,COPY 会为每个数据部分至少创建一个拒绝文件,并根据加载大小和拒绝的行数来创建更多文件。

对于除 COPY LOCAL 以外的所有数据加载,COPY 的行为如下所示:

文件名的最大长度

在一个语句中加载多个输入文件时,需要为每个文件指定完整的路径名称。请牢记,将较长的输入文件名与拒绝数据文件名组合使用可能会超出操作系统的最大长度(通常为 255 个字符)。若要解决文件名超出最大长度的问题,请使用一个与默认路径不同的拒绝数据文件路径,例如 \tmp\\<shorter-file-name>

2 - 将拒绝的数据保存到表中

配合使用 REJECTED DATA 参数和 AS TABLE 子句可指定要将拒绝的数据保存到的表。将拒绝的数据保存到文件与使用 AS TABLE 子句是互斥的。

使用 AS TABLE 子句时,Vertica 会创建一个新表(如果不存在表)或将其附加到现有表。如果加载期间未发生解析拒绝,则表示表存在但却为空。下次加载数据时,Vertica 会将任何拒绝的行插入到现有表中。

加载拒绝表是一种特殊类型的表,其功能和限制如下:

  • 支持 SELECT 语句

  • 可以使用 DROP TABLE

  • 不能创建于 COPY 语句之外

  • 不支持 DML 和 DDL 活动

  • 并非 K-safe

若要使拒绝表中的数据变得 K-safe,可执行下列操作之一:

  • 编写一条 CREATE TABLE..AS 语句,如下例:

    => CREATE TABLE new_table AS SELECT * FROM rejected_table;
    
  • 创建一个表以存储拒绝的记录,并对新表运行 INSERT..SELECT 操作

使用 COPY NO COMMIT

如果 COPY 语句包含选项 NO COMMITREJECTED DATA AS TABLE,并且 reject-table 尚不存在,则 Vertica 分析数据库会将拒绝数据表保存为 LOCAL TEMP 表,并返回一条指示正在创建 LOCAL TEMP 表的消息。

拒绝数据表对于提取-加载-转换工作流很有用,在这些工作流程中,您可能会更频繁地使用临时表。拒绝数据表可让您快速加载数据并确定无法加载的记录。如果您将数据加载到使用 ON COMMIT DELETE 子句创建的临时表,则不会提交 COPY 操作。

拒绝数据表记录的位置

使用 REJECTED DATA AS TABLE table_name 选项将拒绝的记录保存到表中时,表数据将保存到数据库数据子目录 RejectionTableData 中。例如,对于 VMart 数据库,表数据文件的位置为:

/home/dbadmin/VMart/v_vmart_node0001_data/RejectionTableData

拒绝数据表包括拒绝数据和拒绝(异常)原因以及其他数据列(在下面加以介绍)。Vertica 建议您定期删除不再需要的任何拒绝数据表。

查询拒绝数据表

如果在使用 COPY 加载数据时指定了拒绝数据表,则可在加载操作完成后查询该表,以获取有关拒绝数据的信息。例如:

  1. 创建 loader 表:

    => CREATE TABLE loader(a INT)
    CREATE TABLE
    
  2. 使用 COPY 加载值并将拒绝数据保存到表 loader_rejects 中:

    => COPY loader FROM STDIN REJECTED DATA AS TABLE loader_rejects;
    Enter data to be copied followed by a newline.
    End with a backslash and a period on a line by itself.
    >> 1
    >> 2
    >> 3
    >> a
    >> \.
    
  3. 加载数据后查询 loader 表:

    => SELECT * FROM loader;
     x
    ---
     1
     2
     3
    (3 rows)
    
  4. 查询 loader_rejects 表以查看其列行:

    => SELECT * FROM loader_rejects;
    -[ RECORD 1 ]-------------+--------------------------------------------
    node_name                 | v_vmart_node0001
    file_name                 | STDIN
    session_id                | v_vmart_node0001.example.-24016:0x3439
    transaction_id            | 45035996274080923
    statement_id              | 1
    batch_number              | 0
    row_number                | 4
    rejected_data             | a
    rejected_data_orig_length | 1
    rejected_reason           | Invalid integer format 'a' for column 1 (x)
    

拒绝数据表具有以下列:

导出拒绝记录表

您可以将列 rejected_data 的内容导出到文件以仅捕获在第一个 COPY 语句期间拒绝的数据。然后,更正文件中的数据,保存数据并加载更新后的文件。

要导出拒绝记录:

  1. 创建示例表:

    => CREATE TABLE t (i int);
    CREATE TABLE
    
  2. 将数据直接复制到表,并使用一个表存储拒绝数据:

    => COPY t FROM STDIN REJECTED DATA AS TABLE t_rejects;
    Enter data to be copied followed by a newline.
    End with a backslash and a period on a line by itself.
    >> 1
    >> 2
    >> 3
    >> 4
    >> a
    >> b
    >> c
    >> \.
    
  3. 仅显示元组,并设置输出格式:

    => \t
    Showing only tuples.
    => \a
    Output format is unaligned.
    
  4. 输出到文件:

    => \o rejected.txt
    => select rejected_data from t_rejects;
    => \o
    
  5. 对已保存的文件使用 cat 命令:

    
    => \! cat rejected.txt
    a
    b
    c
    

文件存在后,您可以修复加载错误,并使用更正的文件作为 COPY 语句的加载输入。

3 - 保存加载异常 (EXCEPTIONS)

COPY 异常包含一些描述为何无法解析某个数据行的说明性消息。EXCEPTIONS 选项允许您指定 COPY 写入异常的文件。如果省略此选项,则 COPY 会将异常文件保存到以下路径: catalog-dir/CopyErrorLogs/tablename-sourcefilename-copy-from-exceptions,其中:

  • catalog-dir 是存放数据库编录文件的目录

  • table 是要加载到的表的名称

  • sourcefile 是要加载的文件的名称

EXCEPTIONS 选项生成的文件指示每个异常的行号和原因。

如果从 STDIN 复制,则源文件名为 STDIN

您可以为数据加载中的单个文件指定拒绝数据和异常文件。在 COPY 语句中使用逗号分隔拒绝数据和异常文件。

您必须在路径中指定文件名才能加载多个输入文件。请记住,将较长的表名与较长的数据文件名结合使用可能会超出操作系统的最大长度(通常为 255 个字符)。若要解决文件名超出最大长度的问题,请使用一个与默认路径不同的异常文件路径,例如 /tmp/<shorter-file-name>

如果您指定 EXCEPTIONS 路径:

  • 对于一个数据文件,路径必须为文件,并且 COPY 将所有信息都存储在此文件中。

  • 对于多个数据文件,路径必须为目录。COPY 在此目录中为每个数据文件创建一个文件。

  • 不将异常文件存储在启动节点上。

  • 只能为每个节点指定一个路径。

如果未指定 EXCEPTIONS 路径,则 COPY 将异常文件存储在默认目录。

4 - COPY 拒绝数据和异常文件

当执行 COPY 语句并且并行处理为 ON(默认设置)时,COPY 创建单独的线程来处理加载文件。通常,线程的数量取决于系统中节点核心的数量。每个节点处理部分加载数据。如果加载总体成功,在加载处理期间发生的所有解析器拒绝都会写入到该节点的特定拒绝数据以及异常文件中。如果加载失败,则拒绝数据文件内容可能不完整或为空。如果您未明确指定文件名,则 COPY 会对拒绝数据文件使用默认名称和位置。请参阅下一个主题以指定您自己的拒绝数据和异常文件。

拒绝数据和异常文件都会保存并存储在每个节点上。此示例将多个文件用作 COPY 输入。由于语句不包括 REJECTED DATAEXCEPTIONS 参数,拒绝数据和异常文件都会写入每个节点的默认位置,即数据库编录子目录 CopyErrorLogs

\set dir `pwd`/data/ \set remote_dir /vertica/test_dev/tmp_ms/
\set file1 '''':dir'C1_large_tbl.dat'''
\set file2 '''':dir'C2_large_tbl.dat'''
\set file3 '''':remote_dir'C3_large_tbl.dat'''
\set file4 '''':remote_dir'C4_large_tbl.dat'''
=>COPY large_tbl FROM :file1 ON site01,:file2 ON site01,
               :file3 ON site02,
               :file4 ON site02
               DELIMITER '|';

指定拒绝的数据和异常文件

使用可选的 COPY REJECTED DATAEXCEPTIONS 参数 'path' 元素可以指定用来存储文件的非默认路径。

如果 path 解析到存储位置,并且调用 COPY 的用户不是超级用户,则需要以下权限:

两个参数也具有可使用指定路径的可选 ONnodename 子句:

...[ EXCEPTIONS 'path' [ ON nodename ] [, ...] ]...[ REJECTED DATA 'path' [ ON nodename ] [, ...] ]

使用 'path' 指定拒绝数据和异常文件(及其相应的参数)的位置时,可选的 ONnodename 子句会将节点上的任何现有拒绝数据和异常文件移动到同一个节点上的指定路径。

将拒绝数据和异常文件保存到单个服务器

COPY 处理完成后,COPY 语句并无可合并异常和拒绝数据文件的功能。查看异常和拒绝数据文件的内容时,需要访问每个节点的特定文件。

将 VSQL 变量用于拒绝数据和异常文件

此示例使用了 vsql 变量来指定要与 exceptionsrejected data 参数(except_s1reject_s1)一起使用的路径和文件名。COPY 语句在启动程序节点上指定了单个输入文件 (large_tbl):

\set dir `pwd`/data/ \set file1 '''':dir'C1_large_tbl.dat'''
\set except_s1 '''':dir'exceptions'''
\set reject_s1 '''':dir'rejections'''

COPY large_tbl FROM :file1 ON site01 DELIMITER '|'
REJECTED DATA :reject_s1 ON site01
EXCEPTIONS :except_s1 ON site01;

此示例使用变量指定了远程节点上的异常和拒绝数据文件(except_s2reject_s2)。COPY 语句包含远程节点上的单个输入文件 (site02):

\set remote_dir /vertica/test_dev/tmp_ms/\set except_s2 '''':remote_dir'exceptions'''
\set reject_s2 '''':remote_dir'rejections'''

COPY large_tbl FROM :file1 ON site02 DELIMITER '|'
REJECTED DATA :reject_s2 ON site02
EXCEPTIONS :except_s2 ON site02;

此示例使用变量来指定异常和拒绝数据文件位于远程节点上(由 :remote_dir 指示)。COPY 语句的输入包括两个节点(site01site02)上的多个数据文件。exceptionsrejected data 选项使用了具有变量的 ON nodename 子句来指示文件的驻留位置(site01site02):

\set dir `pwd`/data/ \set remote_dir /vertica/test_dev/tmp_ms/
\set except_s1 '''':dir''''
\set reject_s1 '''':dir''''
\set except_s2 '''':remote_dir''''
\set reject_s2 '''':remote_dir''''
COPY large_tbl FROM :file1 ON site01,
               :file2 ON site01,
               :file3 ON site02,
               :file4 ON site02
               DELIMITER '|'
               REJECTED DATA :reject_s1 ON site01, :reject_s2 ON site02
               EXCEPTIONS :except_s1 ON site01, :except_s2 ON site02;

5 - COPY LOCAL 拒绝和异常文件

调用 COPY LOCAL(或 COPY LOCAL FROM STDIN)不会自动创建已拒绝的数据和异常文件。此行为与使用 COPY 不同,使用 COPY 将自动保存两种文件,而不管是否使用可选 REJECTED DATAEXCEPTIONS 参数显式指定任一文件。

将 REJECTED DATA 和 EXCEPTIONS 参数与 COPY LOCAL 和 COPY LOCAL FROM STDIN 结合使用,可将相应输出文件保存到客户端。如果使用这些选项,则不会保留已拒绝的数据解析事件(以及描述这些内容的异常文件),即使发生这些事件。

可以使用 COPY LOCAL(或 COPY LOCAL FROM STDIN)加载多个输入文件。如果还使用 REJECTED DATAEXCEPTIONS 选项,该语句会将已拒绝的行和异常写入不同文件。各个文件中分别包含所有已拒绝的行和相应异常,而不管加载了多少输入文件。

如果 COPY LOCAL 不拒绝任何行,则不会创建任何一个文件。

指定拒绝的数据和异常文件

若要将任何已拒绝的数据及异常保存到文件中:

  1. 在 COPY LOCAL(和 COPY LOCAL FROM STDIN)语句中,分别使用 REJECTED DATA 'path'EXCEPTIONS 'path' 参数。

  2. 为这两个选项指定两个不同的文件名。不能为 REJECTED DATAEXCEPTIONS 使用一个文件。

  3. 调用 COPY LOCAL 或 COPY LOCAL FROM STDIN 时,指定的文件无需预先存在。如果预先存在,COPY LOCAL 必须能够覆盖这些文件。

可以通过 vsql 变量指定路径和文件名:

\set rejected ../except_reject/copyLocal.rejected
\set exceptions ../except_reject/copyLocal.exceptions

使用 COPY LOCAL 或 COPY LOCAL FROM STDIN 语句时,使用相应参数为文件指定变量名称:

=> COPY large_tbl FROM LOCAL rejected data :rejected exceptions :exceptions;
=> COPY large_tbl FROM LOCAL STDIN rejected data :rejected exceptions :exceptions;