如何为含嵌套数据的Hive表按嵌套字段创建分区?
解决Hive中用Struct嵌套字段作为分区列的问题
嘿,我明白你遇到的问题了——Hive确实不支持直接将嵌套Struct里的字段(比如col1.country)作为分区列,因为分区列必须是表的顶层直接列,不能引用嵌套结构中的字段。不过咱们可以通过两个实用方法来实现你的需求:把嵌套字段提取为顶层列,再用这些顶层列做分区。
方法一:用JsonSerDe的映射功能直接提取嵌套字段
你可以借助org.openx.data.jsonserde.JsonSerDe的mapping配置,把JSON里的嵌套字段直接映射到表的顶层列,然后用这些顶层列作为分区列。具体建表语句如下:
CREATE TABLE logs( country string, page string, date string ) PARTITIONED BY (country string, page string, date string) ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' WITH SERDEPROPERTIES ( "mapping.country" = "col1.country", "mapping.page" = "col1.page", "mapping.date" = "col1.date" ) LOCATION 's3a://application-logs/sample/' ;
这里的WITH SERDEPROPERTIES部分就是告诉SerDe:把JSON中col1.country的值映射到表的country列,以此类推。这样表的顶层列就直接对应了你要分区的字段,完美满足Hive对分区列的要求。
方法二:保留原Struct列,同时提取顶层列用于分区
如果你还需要保留原来的col1 Struct列,可以在表中同时定义Struct列和顶层列,再用顶层列做分区:
CREATE TABLE logs( col1 struct<country:string, page:string, date:string>, country string, page string, date string ) PARTITIONED BY (country string, page string, date string) ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' WITH SERDEPROPERTIES ( "mapping.country" = "col1.country", "mapping.page" = "col1.page", "mapping.date" = "col1.date" ) LOCATION 's3a://application-logs/sample/' ;
加载数据时的关键配置
如果要自动创建分区(动态分区),需要先开启Hive的动态分区参数:
SET hive.exec.dynamic.partition=true; SET hive.exec.dynamic.partition.mode=nonstrict;
之后可以用INSERT OVERWRITE语句从原始数据(比如临时表)加载数据到分区表中,示例如下:
INSERT OVERWRITE TABLE logs PARTITION(country, page, date) SELECT col1, col1.country, col1.page, col1.date FROM raw_logs;
为什么直接用col1.country不行?
Hive的分区机制是基于表的顶层列设计的,分区列会被用来组织HDFS上的目录结构(比如country=India/page=/signup/date=2018-01-01/),它无法直接解析嵌套Struct的路径作为分区列的来源,所以必须先把嵌套字段提升为顶层列才行。
内容的提问来源于stack exchange,提问作者midNight
相关产品推荐
相关产品推荐

