Athena执行INSERT遇HiveIgnoreKeyTextOutputFormat格式错误
问题根因
报错由多个配置错误共同触发,按影响优先级排序:
- 核心错误是表定义的SerDe与存储格式错配:两张表都声明使用Parquet序列化类
org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe,但输入/输出格式却配置了纯文本场景用的org.apache.hadoop.mapred.TextInputFormat和org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat,二者完全不兼容。Athena执行写入时会校验目标表的格式组合合法性,直接抛出不支持错误。 - 建表语句本身存在语法问题:你贴出的table2定义中,非分区字段列表最后一个字段
calc_dt后多余逗号,且字段列表缺少闭合右括号,属于SQL语法错误。 - 两张表S3路径配置冲突:两个外部表都指向同一个S3路径
s3://foobucket/object-thing,即使其他配置正确,写入时也会出现数据覆盖、查询结果混乱的问题。 - INSERT语句存在低级错误:你写的目标表是
tabl2,比实际表名table2少了一个字母e,且未考虑两张表分区字段的顺序差异,直接用SELECT *会导致列错位、分区值写入异常。
修复步骤
按以下顺序操作即可解决问题:
1. 重建表修正格式与路径配置
删除原有错误定义的表(删除外部表不会清除S3上的底层数据),使用匹配的格式参数重建,必须给两张表指定独立的S3存储路径:
如果底层文件是Parquet格式,直接用STORED AS PARQUET即可,Athena会自动匹配正确的SerDe、输入输出格式类,不需要手动写全类名:
-- 重建table1 CREATE EXTERNAL TABLE IF NOT EXISTS table1( `mac_address` string, `node` string, `wave_found` string, `wave_data` string, `calc_dt` string, `load_dt` string ) PARTITIONED BY (`site_id` string) STORED AS PARQUET LOCATION 's3://foobucket/table1/' -- 替换为table1专属的独立S3路径 TBLPROPERTIES ('has_encrypted_data'='false'); -- 重建table2 CREATE EXTERNAL TABLE IF NOT EXISTS table2( `mac_address` string, `node` string, `wave_found` string, `wave_data` string, `calc_dt` string ) PARTITIONED BY ( `load_dt` string, `site_id` string ) STORED AS PARQUET LOCATION 's3://foobucket/table2/' -- 替换为table2专属的独立S3路径,不能和table1相同 TBLPROPERTIES ('has_encrypted_data'='false');
如果底层存储的是CSV/TSV等纯文本文件,不要使用Parquet SerDe,换成org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe,同时声明STORED AS TEXTFILE即可。
2. 加载分区元数据
重建表后执行分区修复命令,同步S3上已有的分区信息到表元数据:
MSCK REPAIR TABLE table1; MSCK REPAIR TABLE table2;
3. 执行正确的INSERT语句
不要用SELECT *,显式指定所有列,保证列顺序和目标表的普通列+分区列顺序完全匹配,同时修正表名拼写错误:
INSERT INTO table2 PARTITION (load_dt, site_id) SELECT mac_address, node, wave_found, wave_data, calc_dt, load_dt, site_id FROM table1;
执行写入前可以先单独运行SELECT部分的语句,确认返回的列数、字段值、分区值都符合预期,再执行写入操作。
内容的提问来源于stack exchange,提问作者nate
相关产品推荐
相关产品推荐

