
基于Hive的数据仓库中需要做一张累积快照表,记录了客户发生各个行为的具体日期,比如激活日期、注册日期、申请日期、创建订单日期等等。
这张表需要以激活日期作为分区时间,便于业务查询。
激活日期将近500个日期,在一次性将所有数据全量插入目标分区的时候所有reduce报OOM。
二、解决过程
首先增加reduce端的内存,set mapreduce.reduce.java.opts = -Xmx3072m;set mapreduce.reduce.memory.mb = 3072;最后将内存设置到集群最高内存,仍然报OOM。
再分析源数据的分类,发现源数据存在以前的测试数据,这样会造成有的分区日期只有一条数据,有的分区天数有几十万数据,数据存在严重的倾斜。
解决方法有两种。
第一种在HQL末尾加上distribute by和sort by,或者cluster by。如下:
insert overwrite table loan_f_milestone partition(day)
select *,
to_date(atv_tim)
from loan_f_milestone_tmp12
distribute by to_date(atv_tim)
sort by to_date(atv_tim)
--cluster by to_date(atv_tim)
distribute by按照指定的字段将数据划分到不同的输出reduce中,可以保证每个reduce处理的数据范围不重叠,每个分区内的数据是没有排序的。
sort by保证一个reduce内的数据按照指定字段排序。
cluster by除了有distribute by的功能,还有sort by的功能,所以最终的结果是每个reduce处理的数据范围不重叠,而且每个reduce内的数据按照指定字段排序,而且可以做到全局排序。
所以第二种方式是设置set hive.optimize.sort.dynamic.partition=true;会将动态分区字段全局排序。
一、Hive only:加载分区数据的快捷方法
如果指定的分区不存在Hive将创建新的分区
这个命令将:
(1)如果不存在的话添加分区到表的元数据
(2)如果存在的话,创建子目录:/user/hive/warehouse/call_logs/call_date=2014-10-02
(3)移动HDFS文件call-20141002.log到分区子目录
二、查看、添加和移除分区
(1)查看当前表分区
(2)使用ALTER TABLE添加或删除分区
三、 从已存在的分区目录创建分区
(1)HDFS的分区目录可以在Hive或Impala之外进行创建和数据,比如:通过Spark或MapReduce应用
(2) Hive中使用MSCK REPAIR TABLE命令来为已存在的表创建分区
四、什么时候使用分区
下列情况使用分区
(1)读取整个数据集需要花费很长时间
(2)查询几乎只对分区字段进行过滤
(3)分区列有合理数量的不同的值
(4)数据生成或ETL过程是按文件或目录名来分段数据的
(5)分区列值不在数据本身
五、什么时候不使用分区
(1)避免把数据分区到很多小数据文件
– 不要对有太多惟一值的列进行分区
(2)注意:当使用动态分区时容易发生
– 比如:按照fname来分区客户表会产生上千个分区
六、 Hive进行分区
在旧的Hive版本中,动态分区默认没有启用 ,通过设置这两个属性启用:
但是在hive分区中我们应该注意一些问题,比如:
(1)注意:Beeline设置的Hive变量只在当前会话有效,系统管理员可以设置永久生效
(2)注意:如果分区列有很多唯一值,将会创建很多分区
另外,我们可以给Hive配置参数来限制分区数 :
(1) hive.exec.max.dynamic.partitions.pernode
查询在某个节点上可以创建的最大动态分区数,默认100
(2) hive.exec.max.dynamic.partitions
一个HiveQL语句可以创建的最大动态分区数 ,默认1000
(3)hive.exec.max.created.files
一个查询总共可以创建的最大动态分区数,默认1000000
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)