1.Hive 是什么,讲一下你理解的 Hive
- 用于数据的统计,提供类 sql 的查询功能,本质上就是将 HQL 转化为 Mapreduce.
- Hive 的数据存储在 hdfs 上。
- Hive 底层数据分析的实现是由 MR 完成。
- 执行程序是运行在 Yarn 上。
2.为什么使用 hive ,hive 的优点,相比较数据库而言
核心点在于 数据量问题,Hive 的数据量是存储在分布式集群的 hdfs 上,所以能存储很大的数据量,而 mysql 存存在本地文件系统中,存储的少量的数据。
由于数据量大,没有索引,Hive 查询数据时需要扫描整张表,又由于 hive 使用 MR 去做数据分析,MR 本身就具有较高的延迟,所以hive 的执行延迟就比较高,mysql 存在本地,数据量小,所以执行延迟就比较低,数据更新问题,hive 是针对数据仓库应用设计的,数据仓库的内容是读多写少的,所以 hive 中不建议对数据的改写,所有的数据都是在加载的时候确定好的。而数据库中的数据经常需要修改。
思考:如何降低 Hive 的延迟,其实就是 Hive 的优化问题,优化的关键点主要在于避免数据倾斜。
3.Hive 数据倾斜问题
Hive的执行是分阶段的,map处理数据量的差异取决于上一个stage的reduce输出,所以如何将数据均匀的分配到各个reduce中,就是解决数据倾斜的根本所在。
1. 找到可能产生数据倾斜的函数尤为关键:
-
如数据量较大的时候,避免使用 count(distinct), count(distinct) 容易产生数据倾斜(原因:某特殊值过多,处理此特殊值的reduce耗时),可考虑使用 group by 代替。
-
大小表 join 时,其中一个表较小,但是 key 集中,分发到 某一个 或某几个 reducer 上的数据量远高于平均值。
解决方法:将key相对分散,并且数据量小的表放在join的左边,这样可以有效减少内存溢出错误发生的几率;再进一步,可以使用map join让小的维度表(1000条以下的记录条数)先进内存。在map端完成reduce。(新版 Hive 中已对大小表的 Join 做了优化,小表放在左边或者或者右边已经没有明显区别)。 -
大表 Join 大表时,注意空 Key 的情况,如果某些 Key 对应的空值较多,那么相同的 key 就会分发到相同的 ruducer 中,从而导致内存不够,如果 空 key 是异常数据造成的,就过滤掉这部分空 key .
如果 空 key 不是异常数据造成的,而且必须包含在 Join 的结果中,此时我们可以将表中 key 为空的字段赋一个随机的值,使得数据均匀地分布在不同地reduce 中。 -
group by之后维度过小,就是 key 的种类比较少,但是每个 key 下的值特别多,导致处理某几个 key 时,reducer 比较耗时。
-
总结原因如下:
1)、key分布不均匀2)、业务数据本身的特性
3)、建表时考虑不周
4)、某些SQL语句本身就有数据倾斜
-
1.3表现:
任务进度长时间维持在99%(或100%),查看任务监控页面,发现只有少量(1个或几个)reduce子任务未完成。因为其处理的数据量和其他reduce差异过大。
单一reduce的记录数与平均记录数差异过大,通常可能达到3倍甚至更多。 最长时长远大于平均时长。
3.2 数据倾斜的解决方案
3.2.1参数调节:
hive.map.aggr=true
Map 端部分聚合,相当于Combiner
hive.groupby.skewindata=true
有数据倾斜的时候进行负载均衡,当该选项设定为 true,生成的查询计划回有两个 MR job.
第一个 MR job ,Map 的输出结果集合会随机分布到 Reducer中,每个 Reducer 做部分聚合操作,并输出结果,这样处理的结果是相同的 Group by key 有可能会被分发到不同的 Reducer 中,从而达到负载均衡的目的;
第二个 MR job ,再根据预处理的数据结果按照 group by key 分布到 Reducer 中(这个过程保证了相同的 key 被分布到同一个 Reducer 中),最后完成最终的聚合操作。