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个;

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwffwg.html