使用awswrangler写入的含数组类型Parquet数据无法查询
问题解决:awswrangler写入含数组列的Parquet后S3 Select/Athena查询失败
问题场景
使用awswrangler将包含数组列的DataFrame写入S3 Parquet数据集后,遇到以下问题:
- S3 Select选择CSV作为输出格式查询时,抛出序列化错误
- Athena无法正常获取数据,即使修改分区元数据也无效
- 切换S3 Select输出格式为JSON,或移除数组列后重新写入,即可正常用CSV查询
重现代码
Python写入代码
events = [{"c1": "12", "c2": [1, 2, 3, 6], "c3": 1234}] df = pd.DataFrame.from_dict(events) wr.s3.to_parquet( df=df, path=f"{bucket}/{path}", partition_cols=partition_cols, dataset=True )
Athena建表&添加分区语句
create external table default.test_wrangler_parquet(c1 string, c2 array<integer>) PARTITIONED BY(c3 string) STORED AS PARQUET LOCATION 's3://test_bucket/tmp/wrangler_parquet/'; alter table default.test_wrangler_parquet add partition (c3='1234')
报错说明
S3 Select报错为序列化错误,提示无法将数组类型的值序列化为CSV格式。
问题根源
- CSV格式的局限性:CSV是扁平的行式格式,不支持原生表示嵌套/数组类型,S3 Select无法自动将Parquet中的数组转换为CSV兼容的结构。
- Parquet数组序列化:awswrangler将Pandas列表列写入Parquet时,默认存储为Parquet的重复类型,Athena能识别该类型,但S3 Select在CSV输出时无法处理这种嵌套类型。
解决方案
方案1:仅查询非数组列(适合无需数组数据的场景)
如果只需要CSV格式的非数组字段,查询时避开数组列即可:
-- S3 Select 查询示例 select c1, c3 from s3object s
方案2:写入前将数组列转为字符串
在写入Parquet前,把Pandas的列表列转为字符串格式,这样S3 Select和Athena都能识别为普通字符串,CSV输出无报错:
events = [{"c1": "12", "c2": [1, 2, 3, 6], "c3": 1234}] df = pd.DataFrame.from_dict(events) # 将数组转为逗号分隔的字符串,也可自定义分隔符 df['c2'] = df['c2'].apply(lambda x: ','.join(map(str, x))) wr.s3.to_parquet( df=df, path=f"{bucket}/{path}", partition_cols=partition_cols, dataset=True )
此时Athena建表时需将c2的类型改为string。
方案3:Athena查询时转换数组为字符串
保留Parquet的数组类型,在Athena查询中用array_join函数将数组转为字符串后再导出CSV:
select c1, array_join(c2, ',') as c2_str, c3 from default.test_wrangler_parquet
内容的提问来源于stack exchange,提问作者Raman
相关产品推荐
相关产品推荐

