hive 动态分区与混合分区

本文深入解析Hive中的静态分区、动态分区、混合分区及多级分区的概念与应用场景,通过实例代码展示如何提升查询效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

hive的分区概念,相信大家都非常了解了。通过将数据放在hdfs不同的文件目录下,查表时,只扫描对应分区下的数据,避免了全表扫描。

提升了查询效率。

关于hive分区,我们还会用到多级分区、动态分区、混合分区,这些概念是什么含义,又该在何时使用呢?

静态分区

先说下静态分区。静态分区就是人为指定分区名。向分区插入数据的时候也要写明写入哪个分区。

我们给出建表,和插入数据的示例代码:

建表语句:

DROP TABLE IF EXISTS ods.employee;
CREATE TABLE IF NOT EXISTS ods.employee(
xjson STRING
)
COMMENT '员工表'
PARTITIONED BY (province,city)
ROW FORMAT DELIMITED

数据插入语句:

ALTER TABLE ods.employee DROP IF EXISTS PARTITION (`province`=${province},`city`=${city});
ALTER TABLE ods.employee ADD IF NOT EXISTS PARTITION (`province`=${province},`city`=${city})
INSERT OVERWRITE TABLE FINAL.employee PARTITION(`province`=${province},`city`=${city})
SELECT
	xjson
	FROM ods.employee_full
WHERE `province`=${province},`city`=${city};
tips:

1.进行drop分区,是为了方便重跑。不去手动增加partition也是可以的。

2.写入时用overwrite也是为了方便使用脚本重跑。

2.province`=${province},`city`=${city} 是为了使用调度执行时,可以穿入不同的参数。避免重复的代码。

 

需要注意的是,

1.我们指定分区的那一列 dt 可以看做hive的伪列,虽然在select查询时,会展现在数据的最后,但不会真正出现在数据中。

2.dt也不应该出现在表的某一列名中,否则会报错。

动态分区

动态分区是相对静态分区的。

动态分区可以根据我们指定的某个字段的值,将数据动态写入对应的分区。

我们指定的字段中每有一个取值,就会生成一个分区。

建表语句示例:

create table ods.employee like ods.employee_tmp;
必配参数:
set hive.exec.dynamici.partition=true; --开启动态分区,默认是false


可配置参数:
    set mapreduce.job.name=ods.ods_mysql_sale_sale_detail; --设置执行任务名称
    set hive.merge.mapredfiles = true; --Map-Reduce的任务结束时合并小文件
    set hive.exec.dynamic.partition.mode=nonstrict; --开启允许所有分区都是动态的,否则必须要有静态分区才能使用。
    set hive.exec.max.dynamic.partitions.pernode=100000;--缺省值是100,指每个mapper或reducer可以创建的最大动态分区个数,如果某个mapper或者reducerchangshi 创建大于这个数目的分区,那么就会报错。
    set hive.exec.max.dynamic.partitions =100000;--缺省值是+1000,指的是一个动态分区创建语句可以创建的最大分区数目,如果超过这个数目就会抛出一个致命错误。
    set hive.exec.max.created.files =1000000; --缺省值是100000,全局 可以创建的最大文件个数。

tips:hive建表时,like关键字可以创建结构完全相同的表。

 

数据插入语句示例:

insert overwrite tableods.employee partition(province,city)
select
	name,
	salary,
	subordinates,
	deductions,
	address,
	province,
	city
from ods.employee_tmp t

hive 会根据最后两个列,决定数据最终写入哪个分区中。

混合分区

了解了静态分区与动态分区。让我们学习下混合分区。

假设这样一种情况,我们使用了动态分区,一张表的某个字段的值,决定了另一张表的分区,

如果由于存在脏数据,或人为指定字段错误,就会在另一张表产生茫茫多的分区。

hive的分区数据也是元数据的一部分,由hdfs的namenode管理,hive启动后,会缓存在内存中。

一级分区过多会影响集群性能。

为了避免这种情况,就该使用混合分区。

混合分区的概念并不复杂,就是混合了动态分区和静态分区。且静态分区应该放到动态分区的前面。

插入数据时,第一级分区写死,第二级分区使用静态分区。这样就有效控制了由于分区过多,

导致文件名过多,影响hdfs性能的问题。

 

建表语句示例和动态分区一样,只是在数据插入时会体现出混合分区。

那么,看下数据插入语句:

insert overwrite tableods.employee partition(province='zhejiang',city)
select
	name,
	salary,
	subordinates,
	deductions,
	address,
	province,
	city
from ods.employee_tmp t

代码的第一行体现了混合分区的用法。

多级分区

多级分区,其实我们在上面一直在使用。这里再提一下,
就是第一级分区下,增加第二级分区。对应hdfs就是嵌套的文件夹。

转载于:https://www.cnblogs.com/drjava/p/10521401.html

# Hive动态分区使用指南 ## 一、动态分区基本概念 动态分区允许Hive根据查询结果自动创建分区,无需预先指定每个分区的值。 ### 静态分区对比 ```mermaid graph LR A[分区方式] --> B[静态分区] A --> C[动态分区] B -->|需手动指定| D["INSERT INTO TABLE PARTITION(dt='20230801')"] C -->|自动推断| E["INSERT INTO TABLE PARTITION(dt)"] ``` ## 二、动态分区配置参数 ### 核心参数配置 ```sql -- 启用动态分区 SET hive.exec.dynamic.partition=true; -- 设置为非严格模式(允许所有分区都是动态的) SET hive.exec.dynamic.partition.mode=nonstrict; -- 每个mapper/reducer可创建的最大分区数 SET hive.exec.max.dynamic.partitions.pernode=100; -- 整个SQL可创建的最大分区数 SET hive.exec.max.dynamic.partitions=1000; -- 全局可创建的最大分区数 SET hive.exec.max.created.files=100000; ``` ## 三、动态分区使用示例 ### 基础用法 ```sql -- 从现有表导入数据(自动按dt,country分区) INSERT OVERWRITE TABLE sales_partitioned PARTITION(dt, country) SELECT order_id, amount, order_dt AS dt, country FROM sales_orders; ``` ### 混合分区(静态+动态) ```sql -- year为静态分区,month为动态分区 INSERT OVERWRITE TABLE logs_partitioned PARTITION(year='2023', month) SELECT log_id, content, month(dt) AS month FROM server_logs WHERE year(dt) = 2023; ``` ## 四、动态分区优化策略 ### 性能优化方法 ```sql -- 1. 合理设置分区字段顺序(高基数字段放后面) SET hive.exec.dynamic.partition.mode=nonstrict; SET hive.optimize.sort.dynamic.partition=true; -- 2. 合并小文件(针对动态分区产生大量小文件问题) SET hive.merge.mapfiles=true; SET hive.merge.mapredfiles=true; SET hive.merge.size.per.task=256000000; SET hive.merge.smallfiles.avgsize=16000000; -- 3. 控制reduce数量 SET mapred.reduce.tasks=50; ``` ## 五、动态分区常见问题 ### 问题排查表 | 问题现象 | 可能原因 | 解决方案 | |---------|---------|---------| | 报错`Dynamic partition strict mode` | 未设置nonstrict模式 | 设置`hive.exec.dynamic.partition.mode=nonstrict` | | 报错`exceeds max created files` | 分区数超过限制 | 增大`hive.exec.max.created.files`值 | | 执行速度慢 | 产生大量小文件 | 配置合并小文件参数 | | 数据倾斜 | 分区字段分布不均 | 调整字段顺序或预处理数据 | ## 六、动态分区最佳实践 ### 生产环境建议 1. **分区字段选择**: - 优先选择离散值字段 - 分区数量控制在100-1000之间 - 避免使用高基数字段(如user_id) 2. **数据预处理**: ```sql -- 对高基数字段做分桶处理 INSERT OVERWRITE TABLE sales_partitioned PARTITION(dt, country) SELECT order_id, amount, dt, CASE WHEN country IN ('US','UK') THEN country ELSE 'Other' END AS country FROM sales_orders; ``` 3. **监控措施**: ```sql -- 检查分区数量是否合理 SHOW PARTITIONS sales_partitioned; -- 分析分区数据分布 ANALYZE TABLE sales_partitioned PARTITION(dt, country) COMPUTE STATISTICS; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值