从S3重新加载已卸载的表数据

时间:2016-01-06 15:52:51

标签: amazon-redshift

使用默认分隔符“|”将~~ 500 gig表卸载到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个记录)。测试集中没有这样的数据。

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

我会发现令人惊讶的是,UNLOAD命令没有逃避记录中的分隔符,因为它正在卸载,但也许这是天真的。

关于我如何能够解决这个问题的任何想法,除了从s3下载每个文件并试图手动修复问题的一些英雄程序之外?我祈祷有一个神奇的COPY命令参数,这将有所帮助。

3 个答案:

答案 0 :(得分:2)

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

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

  1. 创建一个包含单列和长度varchar(max)
  2. 的表(T1)
  3. 使用您确定不会出现在数据中的分隔符将已卸载的数据复制到此表中,例如\ t或\ 001(^ A)

    这是数据在表格中的样子 - enter image description here

  4. 创建一个具有所需列数和数据类型的新表(T2)。
  5. 对于除熟食店之外没有额外PIPES的行 - 插入新表。

    查询应该是这样的 -

    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;
    
  6. 对于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;
    
  7. 注意:

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

    ||是连接

    如果您有任何问题,请与我们联系。

答案 1 :(得分:2)

你必须告诉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;

答案 2 :(得分:1)

创建另一个卸载:

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 '|';

您的卸载数据会在每个列值周围显示引号,如果它在引号中,则不会将管道视为分隔符。