Hive中静态分区和动态分区总结
目录
- 背景
- 第一部分 静态分区
- 第二部分 动态分区
- 第三部分 两者的比较
- 第四部分 动态分区使用的问题
- 参考文献及资料
背景
在Hive中有两种类型的分区:静态分区(Static Partitioning)和动态分区(Dynamic Partitioning)。
- 静态分区。对于静态分区,从字面就可以理解:表的分区数量和分区值是固定的。
- 动态分区。会根据数据自动的创建新的分区。
本文会详细介绍两种分区方法、使用场景以及生产中常见问题和解决方法。
第一部分 静态分区
静态分区的使用场景主要是分区的数量是确定的。例如人力资源信息表中使用“部门”作为分区字段,通常一段时间是静态不变的。例如:
CREATE EXTERNAL TABLE employee_dept (
emp_id INT,
emp_name STRING
) PARTITIONED BY (
dept_name STRING
)
location '/user/employee_dept';
LOAD DATA LOCAL INPATH 'hr.txt'
INTO TABLE employee_dept
PARTITION (dept_name='HR');
上面的外部表以dept_name字段为分区字段,然后导入数据需要指定分区。
第二部分 动态分区
通常在生产业务场景中,我们使用的都是灵活的动态分区。例如我们使用时间字段(天、小时)作为分区字段。新的数据写入会自动根据最新的时间创建分区并写入对应的分区。例如下面的例子:
hive > insert overwrite table order_partition partition (year,month) select order_id, order_date, order_status, substr(order_date,1,4) year, substr(order_date,5,2) month from orders;
FAILED: SemanticException [Error 10096]: Dynamic partition strict mode requires at least one static partition column. To turn this off set hive.exec.dynamic.partition.mode=nonstrict
写入报错。这是因为Hive默认配置不启用动态分区,需要使用前开启配置。开启的方式有两种:
在hive服务配置文件中全局配置;
每次交互时候进行配置(只影响本次交互);
通常我们生产环境使用第二种。
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
其中参数hive.exec.dynamic.partition.mode表示动态分区的模式。默认是strict,表示必须指定至少一个分区为静态分区,nonstrict模式表示允许所有的分区字段都可以使用动态分区。
第三部分 两者的比较
两种分区模式都有各自的使用场景,我们总结如下:
| 静态分区(Static Partitioning) | 动态分区(Dynamic Partitioning) | |
|---|---|---|
| 分区创建 | 数据插入分区之前,需要手动创建每个分区 | 根据表的输入数据动态创建分区 |
| 适用场景 | 需要提前知道所有分区。适用于分区定义得早且数量少的用例 | 有很多分区,无法提前预估新分区,动态分区是合适的 |
另外动态分区的值是MapReduce任务在reduce运行阶段确定的,也就是所有的记录都会distribute by,相同字段(分区字段)的map输出会发到同一个reduce节点去处理,如果数据量大,这是一个很弱的运行性能。而静态分区在编译阶段就确定了,不需要reduce任务处理。所以如果实际业务场景静态分区能解决的,尽量使用静态分区即可。
第四部分 动态分区使用的问题
Hive表中分区架构使得数据按照分区分别存储在HDFS文件系统的各个目录中,查询只要针对指定的目录集合进行查询,而不需要全局查找,提高查询性能。
但是分区不是"银弹",如果分区数据过多,就会在HDFS文件系统中创建大量的目录和文件,对于集群NameNode服务是有性能压力的,NameNode需要将大量元数据信息保留在内存中。另外大分区表在用户查询时候由于分析size太大,也容易造成Metastore服务出现OMM报错。
上面两个现象均在生产环境发生,分别造成NameNode和Metastore不可用。
事实上,Hive为了防止异常生产大量分区,甚至默认动态分区是关闭的。另外对于生成动态分区的数量也做了性能默认限制。
4.1 动态分区创建限制
当我们在一个Mapreduce任务(hive写入会编译成mapreduce任务)中创建大量分区的时候,经常会遇到下面的报错信息:
2015-06-15 17:27:44,614 ERROR [LocalJobRunner Map Task Executor #0]: mr.ExecMapper (ExecMapper.java:map(171)) - org.apache.hadoop.hive.ql.metadata.HiveException: Hive Runtime Error while processing row ....
Caused by: org.apache.hadoop.hive.ql.metadata.HiveFatalException: [Error 20004]: Fatal error occurred when node tried to create too many dynamic partitions. The maximum number of dynamic partitions is controlled by hive.exec.max.dynamic.partitions and hive.exec.max.dynamic.partitions.pernode. Maximum was set to: 256... 10 more
这个报错就是因为Hive对于动态分区创建的限制,涉及的参数有:
hive.exec.max.dynamic.partitions = 1000;
hive.exec.max.dynamic.partitions.pernode = 100;
hive.exec.max.created.files = 10000
hive.exec.max.dynamic.partitions.pernode,参数限制MapReduce任务单个任务(mapper或reducer任务)创建的分区数量为100;hive.exec.max.dynamic.partitions,参数限制单次整体任务创建分区的数量上限为1000个;hive.exec.max.created.files,参数限制所有单次整体map和reduce任务创建的最大文件数量上限为10000个;
以上三个阀值超过就会触发错误,集群会杀死任务。为了解决报错,我们通常将两个参数调大。但是也需要用户对自己的Hive表的分区数量进行合理规划,避免过多的分区。
4.2 特殊分区
如果动态分区列输入的值为NULL或空字符串,则Hive将该行将放入一个特殊分区,其名称由参数hive.exec.default.partition.name控制。默认值为__HIVE_DEFAULT_PARTITION__。
用户可以使用(查看表分区)命令进行查看:
show partitions 'table名称';
# process_date=20160208
#process_date=__HIVE_DEFAULT_PARTITION__
有时候异常生产这些分区数据,需要进行清理。如果使用下面的语句:
ALTER TABLE Table_Name DROP IF EXISTS PARTITION(process_date='__HIVE_DEFAULT_PARTITION__');
这时候Hive会报错:
Error: Error while compiling statement: FAILED: SemanticException Unexpected unknown partitions for (process_date = null) (state=42000,code=40000)
这是Hive一个已知bug(编号:HIVE-11208),在Hive 2.3.0版本修复。
但是有个有修复方法(不建议在生产环境中实施):
-- update the column to be "string"
ALTER TABLE test PARTITION COLUMN (p1 string);
-- remove the default partition
ALTER TABLE test DROP PARTITION (p1 = '__HIVE_DEFAULT_PARTITION__');
-- then revert the column back to "int" type
ALTER TABLE test PARTITION COLUMN (p1 int);
链接:https://cloudera.ericlin.me/2015/07/how-to-drop-hives-default-partition-hive_default_partition-with-int-partition-column/
4.3 乱码分区字段
有时候表分区字段由于处理不当,会出现乱码分区,例如:
hp_stat_time=r_ready%3D91;r_load%3D351
原因是Hive会自动对一些UTF-8字符编码成Unicode(类似网址中中文字符和一些特殊字符的编码处理)。此处%3D解码后是'='。可以使用在线转换进行解码:https://www.matools.com/code-convert-utf8。
最后使用解码后的字段即可(注意分号转义):
alter table dpdw_traffic_base drop partition(hp_stat_time='r_ready=91\;r_load=351');
参考文献及资料
1、动态分区,链接:https://cwiki.apache.org/confluence/display/Hive/DynamicPartitions
2、Hive Tutorial,链接:https://cwiki.apache.org/confluence/display/Hive/Tutorial
3、Apache Hive 中文手册,链接:https://www.docs4dev.com/docs/zh/apache-hive/3.1.1/reference
更多关注公众号:

Hive中静态分区和动态分区总结的更多相关文章
- Hive的静态分区和动态分区
作者:Syn良子 出处:http://www.cnblogs.com/cssdongl/p/6831884.html 转载请注明出处 虽然之前已经用过很多次hive的分区表,但是还是找时间快速回顾总结 ...
- 什么是hive的静态分区和动态分区,它们又有什么区别呢?hive动态分区详解
面试官问我,什么是hive的静态分区和动态分区,这题我会呀. 简述 分区是hive存放数据的一种方式,将列值作为目录来存放数据,就是一个分区,可以有多列. 这样查询时使用分区列进行过滤,只需根据列值直 ...
- 对现有Hive的大表进行动态分区
分区是在处理大型事实表时常用的方法.分区的好处在于缩小查询扫描范围,从而提高速度.分区分为两种:静态分区static partition和动态分区dynamic partition.静态分区和动态分区 ...
- 【HIVE】(2)分区表、二级分区、动态分区、分桶、抽样
分区表: 建表语句中添加:partitioned by (col1 string, col2 string) create table emp_pt(id int, name string, job ...
- jsp中静态include和动态include的区别
jsp中静态include和动态include的区别 动态 INCLUDE 用 jsp:include 动作实现 <jsp:include page="included.jsp&quo ...
- Hive静态分区和动态分区,对应Mysql中的元数据信息
静态分区: 手动指定分区加载数据,就是常说的静态分区的使用.但是在日常工作中用的比较多的是动态分区. 创建: hive> create table order_mulit_partition( ...
- hive SQL 静态分区和 动态分区
Hive 分区介绍: hive中简单介绍分区表(partition table),含动态分区(dynamic partition)与静态分区(static partition) hive中创建分区表没 ...
- Hive静态分区和动态分区
一.静态分区 1.创建分区表 hive (default)> create table order_mulit_partition( > order_number string, > ...
- hive学习(六) 参数和动态分区
1.hive 参数.变量 1.1hive的命名空间: hive当中的参数.变量,都是以命名空间开头
随机推荐
- how to enable vue cli auto open the localhost url
how to enable vue cli auto open the localhost URL bad you must click the link by manually, waste of ...
- 一个模块如何同时支持 ESM 和 CJS
一个模块如何同时支持 ESM 和 CJS 模块转化 webpack + babel refs xgqfrms 2012-2020 www.cnblogs.com 发布文章使用:只允许注册用户才可以访问 ...
- Node.js & process.env & OS Platform checker
Node.js & process.env & OS Platform checker Window 10 Windows 7 ia32 CentOS $ node # process ...
- free Google translator for the personal website
free Google translator for the personal website https://html5.xgqfrms.xyz/
- SMS OTP 表单最佳做法 (短信验证)
<form action="/verify-otp" method="POST"> <input type="text" ...
- transient的作用及序列化
1.transient 介绍 Java中的transient关键字,transient是短暂的意思.对于transient 修饰的成员变量,在类的实例对象的序列化处理过程中会被忽略. 因此,trans ...
- 2021-2-22:请你说下 CAP 理论并举例
CAP CAP 理论是分布式系统中的一个老生常谈的理论了,最早由 Eric Brewer 在一个讲座中提出.在这个讲座中,在传统 ACID 理论以及当时比较流行但是比较抽象的的设计指导理论 BASE ...
- JDBC概念理解
##JDBC: 概念:Java DataBase Connectivity Java 数据库连接 Java语言操作数据库 JDBC本质:其实是官方(sun公司)定义的一套操作所有关系型数据库的规则 ...
- 处理XML数据应用实践
摘要:GaussDB(DWS)支持XML数据类型及丰富的XML解析函数,可实现关系数据和XML数据的映射管理功能. XML概述 XML是可扩展的标识语言(eXtensible Markup Langu ...
- Java基础语法:static修饰符
一.静态变量 描述: 在类中,使用'static'修饰的成员变量,就是静态变量,反之为非静态变量. 区别: 静态变量属于类的,可以使用类名来访问:非静态变量是属于对象的,必须使用对象来访问. 静态变量 ...