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

Posted

技术标签:

【中文标题】从 S3 重新加载已卸载的表数据【英文标题】:Reloading unloaded table data from S3 【发布时间】:2016-01-06 15:52:50 【问题描述】:

使用默认分隔符“|”将 ~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 命令参数可以在这里提供帮助。

【问题讨论】:

如果您好奇,我能够恢复最初生成表的原始日志级别数据,并在此基础上重新生成表。 【参考方案1】:

您必须告诉 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】:

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

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

    使用单列和长度 varchar(max) 创建一个表 (T1)

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

    这是表格中数据的样子 -

    创建具有所需列数和数据类型的新表 (T2)。

    对于除了分隔符之外没有额外管道的行 - 插入到您的新表中。

    查询应该是这样的 -

    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;
    

    对于具有除定界符以外的 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 数量。

|| 是串联

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

【讨论】:

【参考方案3】:

创建另一个卸载:

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

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

【讨论】:

谢谢,但不幸的是,第一次卸载后表格被截断了。

以上是关于从 S3 重新加载已卸载的表数据的主要内容,如果未能解决你的问题,请参考以下文章

iOS - 从其他类的表中重新加载数据

使用 Airflow 将数据从 Redshift 卸载到 S3

递归地将数据从 redshift 卸载到 S3 存储桶

将数据从 Amazon redshift 卸载到 Amazon s3

如何使用 aws unload 命令将数据从 AWS Redshift 卸载到 s3?

从 S3 加载 spark DF,多个文件。这些方法中哪一种最好?