正在从 S3 重新加载卸载的 table 数据

Reloading unloaded table data from S3

使用默认分隔符“|”将 ~500 gig table 卸载到 S3。该命令看起来像这样...

UNLOAD ('select * from some_table')
TO 's3://some-path/unloaded-tables/some-table/'
CREDENTIALS 'aws_access_key_id=xyz;  aws_secret_access_key=abc'
MANIFEST;

我正在尝试使用如下命令将此数据重新加载回 some_table。

COPY some_table 
FROM 's3://some-path/unloaded-tables/some-table/manifest' 
CREDENTIALS 'aws_access_key_id=xyz;  aws_secret_access_key=abc'
MANIFEST
DELIMITER '|';

对数据的一个子集进行了 运行 测试,以确保它可以重新加载。然而,事实证明数据集中的一列 可以 包含一个管道(似乎有大约 %20 的记录)。 None测试集中有这样的数据

现在尝试加载数据时,无法正确解析包含管道的记录。

令我感到惊讶的是,UNLOAD 命令在卸载时没有转义记录中的定界符,但这也许是幼稚的。

如果没有一些从 s3 下载每个文件并尝试手动修复问题的英雄程序,关于我如何解决这个问题的任何想法?我祈祷有一个神奇的 COPY 命令参数可以在这里提供帮助。

如果您可以将此数据一次加载到其他 table,然后将其拆分到其他 table,这就是您可以做的 -

示例 - 假设您的数据有 3 列和 2 个管道,但其中一个有一个额外的管道。 你用“|”将它卸载到 S3分隔符。

  1. 创建具有单列和长度 varchar(max)

    的 table (T1)
  2. 将卸载的数据复制到此 table 中,并使用您确定不会出现在数据中的分隔符 - 例如 \t 或 \001 (^A)

    这就是数据在 table 中的样子 -

  3. 创建一个具有所需列数和数据类型的新 table (T2)。

  4. 对于除了分隔符之外没有额外 PIPES 的行 - 插入到新的 table.

    查询应该是这样的-

    insert into T2 
    select split_part(X,"|",1),
           split_part(X,"|",2),
           split_part(X,"|",3)
    from T1
    where len(X) - len(replace(X,"|","")) = 3;
    
  5. 对于除定界符以外的 PIPE 行,将拆分合并为一个并插入到 T2。

    insert into T2 
    select split_part(X,"|",1),
           split_part(X,"|",2),
           split_part(X,"|",3) || split_part(X,"|",4)
    from T1
    where len(X) - len(replace(X,"|","")) = 4;
    

注:

len(X) - len(replace(X,"|","")) = 3; 显示您单元格中的 PIPE 数量。

||是串联

如果您有任何问题,请告诉我。

创建另一个卸载:

UNLOAD ('select * from some_table')
TO 's3://some-path/unloaded-tables/some-table/'
CREDENTIALS 'aws_access_key_id=xyz;  aws_secret_access_key=abc'
DELIMITER '|' ADDQUOTES;

您的 copy 命令将如下所示:

COPY some_table 
FROM 's3://some-path/unloaded-tables/some-table/manifest' 
CREDENTIALS 'aws_access_key_id=xyz;  aws_secret_access_key=abc'
REMOVEQUOTES
DELIMITER '|';

您卸载的数据将在每个列值周围加上引号,如果它在引号中,它不会将竖线视为分隔符。

您必须告诉 Redshift 在您的卸载和复制命令中显式转义分隔符,并将所有字段用引号引起来。

UNLOAD ('statement')
TO 's3://bucket'
CREDENTIALS 'aws_access_key_id=...;aws_secret_access_key=...'
GZIP 
DELIMITER as '|'
ESCAPE ADDQUOTES ALLOWOVERWRITE;

然后复制

COPY table
FROM 's3path'
CREDENTIALS 'credentials'
GZIP REMOVEQUOTES ESCAPE DELIMITER '|'
FILLRECORD EMPTYASNULL BLANKSASNULL TIMEFORMAT 'auto'
COMPUPDATE off STATUPDATE off;