使用COPY命令从Parquet导入Redshift时突破Athena/Glue varchar限制
解决Redshift写入超长JSON到Super类型列的COPY报错问题
问题原因分析
你遇到的报错String value exceeds the max size of 65535 bytes,核心原因是**SERIALIZETOJSON参数的行为限制**:
当使用FORMAT PARQUET SERIALIZETOJSON时,Redshift会先将Parquet文件中的字符串类型列序列化为JSON字符串,这个过程中会默认套用varchar(65535)的长度检查——哪怕目标列是Super类型,也会在序列化阶段触发长度限制,导致报错。和Glue表无关,COPY命令本身不会自动创建Glue表。
解决方案
方案一:预处理JSON字符串为结构化类型,直接用Parquet导入
将DataFrame中的超长JSON字符串转成Python的字典/列表(结构化JSON对象),这样Parquet会将其存储为struct/array类型,COPY时可直接映射到Super类型,无需序列化:
- 预处理DataFrame:
import json import pandas as pd import awswrangler as wr # 安全解析JSON,处理格式错误 def safe_json_load(s): try: return json.loads(s) except Exception: return {} df['long_json_col1'] = df['long_json_col1'].apply(safe_json_load) df['long_json_col2'] = df['long_json_col2'].apply(safe_json_load) - 保存Parquet到S3:
wr.s3.to_parquet( df=df, path="s3://your-bucket/parquet-dataset-path/", dataset=True, mode="overwrite" ) - 执行COPY命令(去掉SERIALIZETOJSON):
Parquet中的struct/array类型会直接映射到Redshift的Super类型,跳过字符串序列化步骤,避免长度限制。COPY schema.target_table FROM 's3://your-bucket/parquet-dataset-path/' IAM_ROLE 'arn:aws:iam::your-account-id:role/your-redshift-role' FORMAT PARQUET;
方案二:改用JSON Lines格式导入
如果不想预处理JSON字符串,可以将DataFrame保存为JSON Lines(每行一个JSON对象)格式,直接COPY到Super列:
- 保存JSON Lines到S3:
df.to_json( "s3://your-bucket/json-lines-path/data.jsonl", orient="records", lines=True, force_ascii=False ) - 执行COPY命令:
Redshift会自动将JSON字段解析为Super类型,全程不会将JSON当作varchar处理,自然不会触发65535字节限制。COPY schema.target_table FROM 's3://your-bucket/json-lines-path/' IAM_ROLE 'arn:aws:iam::your-account-id:role/your-redshift-role' FORMAT JSON 'auto';
额外建议
- 若数据量较小,也可以尝试用
wr.redshift.write_sql()直接插入数据,无需中间存储,但大数据量下COPY的效率更高。 - 预处理JSON时务必加入异常处理,避免因个别格式错误的JSON导致整个导入失败。
内容的提问来源于stack exchange,提问作者Liborio
相关产品推荐
相关产品推荐

