AWS Athena定义varchar(40),生成DDL却显示varchar(65535)
问题
通过以下SQL在AWS Athena创建外部表:
CREATE EXTERNAL TABLE IF NOT EXISTS report ( `token` varchar(40), ) PARTITIONED BY ( `created_hour` string) ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' WITH SERDEPROPERTIES ( 'serialization.format' = '1' ) LOCATION 's3://demo-kinesis-athena/' TBLPROPERTIES ( 'has_encrypted_data'='false', 'projection.created_hour.format' = 'yyyy/MM/dd/HH', 'projection.created_hour.interval' = '1', 'projection.created_hour.interval.unit' = 'HOURS', 'projection.created_hour.range' = '2018/01/01/00,NOW', 'projection.created_hour.type' = 'date', 'projection.enabled' = 'true', 'storage.location.template' = 's3://demo-kinesis-athena/${created_hour}' );
表创建成功,但生成表DDL时,token字段类型显示为varchar(65535),与定义的长度不符,如何解决?
解决方案
原因
你使用的org.openx.data.jsonserde.JsonSerDe(OpenX JSON SerDe)会忽略varchar字段的长度约束,默认将其映射为Athena支持的最大长度varchar(65535)——因为JSON格式本身没有字段长度限制,该SerDe不会保留长度元数据。
解决办法
- 替换为Athena内置JSON SerDe:使用
org.apache.hive.hcatalog.data.JsonSerDe替代OpenX的SerDe,内置SerDe会保留varchar的长度定义。修改后的建表语句如下:
CREATE EXTERNAL TABLE IF NOT EXISTS report ( `token` varchar(40), ) PARTITIONED BY ( `created_hour` string) ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe' LOCATION 's3://demo-kinesis-athena/' TBLPROPERTIES ( 'has_encrypted_data'='false', 'projection.created_hour.format' = 'yyyy/MM/dd/HH', 'projection.created_hour.interval' = '1', 'projection.created_hour.interval.unit' = 'HOURS', 'projection.created_hour.range' = '2018/01/01/00,NOW', 'projection.created_hour.type' = 'date', 'projection.enabled' = 'true', 'storage.location.template' = 's3://demo-kinesis-athena/${created_hour}' );
- 改用char类型(适合固定长度场景):如果必须保留OpenX SerDe,可以将
varchar(40)改为char(40),该SerDe会保留char的长度定义,但注意char类型会自动填充空格至指定长度,仅适合固定长度的字段场景。 - 业务逻辑层面限制(不推荐):如果以上两种方式都不可行,可接受
varchar(65535)的字段类型,在查询时通过substring(token, 1, 40)截断长度,或在数据写入时控制字段长度,但这种方式无法在表结构层面约束数据。
内容的提问来源于stack exchange,提问作者UMR
相关产品推荐
相关产品推荐

