Redshift COPY 无法从 S3 读取 tar.gz。错误代码 1216。缺少换行符:在位置 1 发现意外字符 0x2f

Redshift COPY failing to read tar.gz from S3. Error code 1216. Missing newline: Unexpected character 0x2f found at location 1

tar --列表

当我列出 tar.gz 文件的内容时,我得到以下信息:

$ tar --list --verbose --file /tmp/tmp.tar.gz | head -5
drwxrwxr-x user/user     0 2015-07-22 19:51 ./
-rw-rw-r-- user/user 113376 2015-07-13 06:29 ./NASDAQ_20140324.txt
-rw-rw-r-- user/user 116101 2015-07-13 06:29 ./NASDAQ_20140602.txt
-rw-rw-r-- user/user 120710 2015-07-13 06:30 ./NASDAQ_20140822.txt
-rw-rw-r-- user/user 123969 2015-07-13 06:31 ./NASDAQ_20141104.txt

zcat

当我 zcat 我得到的文件时:

$ zcat /tmp/tmp.tar.gz | head -5
./0000775000175000017500000000000012553663674010514 5ustar  useruser./NASDAQ_20140324.txt0000664000175000017500000033534012550547030013173 0ustar  useruserAAIT,D,20140324,31.1,31.29,30.97,31.11,14600
AAL,D,20140324,36.25,36.86,36.03,36.8,6514500
AAME,D,20140324,3.71,3.75,3.71,3.73,5900
AAOI,D,20140324,25.76,26.15,24.84,25.81,213300
AAON,D,20140324,19.2267,19.2933,18.8667,19.1667,149700

stl_load_errors

s3://<bucket>/<key> 中找到的 <files> 来自 stl_load_errors 的问题(仅列出相关列)是:

filename        =>  <file>.tar.gz
line_number     =>  1
colname         =>  (empty)
type            =>  (empty)
col_length      =>  (empty)
position        =>  0
raw_line        =>  ./
raw_field_value =>  (empty)
err_code        =>  1216
err_reason      =>  Missing newline: Unexpected character 0x2f found at location 1

进一步分解:

Note: On line_number = 1, at the position of 0, the raw_line has ./, which apart from the period (.) is the forward slash character mentioned in the error_reason

这似乎与 zcat 输出提供的 一致,后者的第一行格式错误。这是不是红鲱鱼,我不知道。


但是等等,还有更多...

The text files originally come zipped, so I convert the zip archive files into tar.gz archive files in this manner ...

  1. zip 文件被unzip编辑到临时目录
  2. 临时目录中的文本文件被转换
    2.1. sed 从文件中删除 header 行并通过管道传输到 ...
    2.2. awk 在输出前添加一列并保存到临时文本文件
    2.3. mv 只是将临时文件重命名为临时工作目录中的原始文件名
  3. tar.gz 文件是从转换后的临时文件创建的

1.

unzip -q "${in_archive_file_path}" -d "${tmp_working_dir}"

2.

for in_file_path in `find "${tmp_working_dir}" -type f -iname "*_????????.txt" | sort -n`;
do  
    sed -e "1{/^${quote_header_mask}/d;}" "${in_file_path}" |
    awk -v in_var="${exchange}" '{print in_var,[=15=]}' OFS=, > "${tmp_working_dir}/tmp.txt"
    mv -f "${tmp_working_dir}/tmp.txt" "${in_file_path}"
done

quote_header_mask="<ticker>,<date>,<open>,<high>,<low>,<close>,<vol>"

3.

tar c -C "${tmp_working_dir}/" . | pigz --best -p4 > "${working_dir}/tmp.tar.gz"
mv -f "${working_dir}/tmp.tar.gz" "${out_file_path}"

working_dir是parent到tmp_working_dir


复制

copy source.quote_daily
(
    exchange_code
    ,ticker_code    
    ,date_key_local
    ,price_open     
    ,price_high     
    ,price_low      
    ,price_close    
    ,volume
)
from 's3://<bucket>/<key>' 
credentials 'aws_access_key_id=<key value>;aws_secret_access_key=<secret key value>' 
delimiter  ','
gzip
trimblanks
compupdate off
statupdate off
;   

问题

  1. zcat 是否为我指明了关于 Redshift 解压缩存档时 "see" 的正确方向...?
  2. ...这可能意味着我的 tar.gz 创建脚本搞砸了?

我认为 Redshift 不支持为 COPY 命令导入归档文件 (tar)。您应该使用 gzip 格式压缩每个文件并将它们上传到 s3。 s3上的文件应该是这样的

s3://<bucket>/<key>/XXXXX.gz
s3://<bucket>/<key>/YYYYY.gz
...

您可以使用单个 COPY 命令复制所有 gz 文件,方法是指定目录路径,如 from 's3://<bucket>/<key>/'

这是我使用的数据的问题。

有些文件的 header 与我在第 2 部分中为变量 ${quote_header_mask} 设置的文件不同,因此 header 行没有被删除。

这些文件进入了 COPY 命令,失败的原因是 header 仍然存在,而我的 COPY 没有为任何 header 做准备完全没有。