使用具有不同列顺序的 CSV 加载外部 Redshift Spectrum table

Load Redshift Spectrum external table with CSVs with differing column order

This 没有答案,我有一个类似的问题,但我会展开它。

假设我在 s3://test_path/ 中有 3 个 CSV 文件。我想创建一个外部 table 并用这些 CSV 中的数据填充它。但是,不仅 CSV 中的列顺序不同,而且某些 CSV 中可能缺少某些列。

Redshift Spectrum 是否能够满足我的需求?

a.csv:

id,name,type
a1,apple,1
a2,banana,2

b.csv:

type,id,name
1,b1,orange
2,b2,lemon

c.csv:

name,id
kiwi,c1

我在我的 Redshift 集群上的 Redshift 查询编辑器 v2 中通过 运行 创建了外部 database/schema 和 table:

CREATE EXTERNAL SCHEMA test_schema
FROM DATA CATALOG
DATABASE 'test_db'
REGION 'region'
IAM_ROLE 'iam_role'
CREATE EXTERNAL DATABASE IF NOT EXISTS
;
CREATE EXTERNAL TABLE test_schema.test_table (
  "id" VARCHAR,
  "name" VARCHAR,
  "type" SMALLINT
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
STORED AS TEXTFILE
LOCATION 's3://test_path/'
TABLE PROPERTIES ('skip.header.line.count'='1')
;

我希望 SELECT * FROM test_schema.test_table 产生:

id name type
a1 apple 1
a2 banana 2
b1 orange 1
b2 lemon 2
c1 kiwi NULL

相反,我得到:

id name type
a1 apple 1
a2 banana 2
1 b1 NULL
2 b2 NULL
kiwi c1 NULL

似乎 Redshift Spectrum 无法像 pandas.concat() 对具有不同列顺序的数据帧那样按名称跨文件匹配列。

不,您的数据需要转换以对齐文件之间的数据。您的 Spectrum DDL 指定忽略 CSV 的第一行,因此您需要的信息甚至都不会被读取。

如果您希望将这些文件用作一个 Spectrum table,您将需要转换它们以对齐列并将新文件存储到 S3。如果您还有一段支持代码从每个文件读取列顺序,则可以使用 Redshift 执行此操作。您可以编写一个 Lambda 来轻松完成此操作,或者如果您的 CSV 文件相当简单,那么 Glue 爬虫就可以工作。几乎任何 ETL 工具也可以做到这一点。有很多选择,但这些文件并未按原样准备好 Spectrum。