hive--优化
总结
- ps:本段总结只是方便我的全局理解,如果哪里不合理欢迎指导
- 对于一段sql,我们可以分析一下
SQL执行顺序
- (7) SELECT
- (8) DISTINCT <select_list>
- (1) FROM <left_table>
- (3) <join_type> JOIN <right_table>
- (2) ON <join_condition>
- (4) WHERE <where_condition>
- (5) GROUP BY <group_by_list>
- (6) HAVING <having_condition>
- (9) ORDER BY <order_by_condition>
- (10) LIMIT <limit_number>
- FROM ->on-> join-> WHERE -> GROUP BY -> HAVING -> SELECT -> DISTINCT -> UNION -> ORDER BY-> limit
这些关键字决定了什么
select 1 from 2 where 3 group by 4 having 5 order by 6 limit 7
- 1-决定了结果有哪些列:要么是已存在的列,要么是函数生成的列,列的过滤
- 2-决定了读取数据的数据源
- 3-决定了对哪些行进行过滤
- 4-按照什么条件进行分组
- 5-分组以后对哪些行进行过滤
- 6-按照什么条件进行排序
- 7-限制输出
对应怎么优化呢?
- Hive会将一个查询转化成一个或者多个阶段。这样的阶段可以是MapReduce阶段、抽样阶段、合并阶段、limit阶段。
- 我们知道hive底层是mapreduce,对于hive来说,优化就可以分为两个方向去优化,即sql优化及参数优化,其
本质大部分都是针对mapreduce进行优化
,比如减少数据量,从而减少数据传输;比如合理的map数和reduce数,从而并行执行。
首先,针对mr的input阶段
- 减少数据量
- 如果是分区表,进行数据查询指定分区,即尽量
在where中使用分区字段
,减少数据量
- 如果逻辑中有临时表,做好列裁剪(
即只保留我们需要的列
),减少数据量
- 如果有join,
先过滤在join
,减少数据量
第二,针对mr的map阶段
- 一个小文件会启动一个map,如果有很多个小文件,可能一个map任务启动和初始化的时间远远大于逻辑处理的时间,也就是说我们可以合并小文件,来
减少map数
,配置一个combine参数可以执行前进行小文将合并
,一个merge参数执行mr结束时合并小文件
,同时也可以配置最小/大切片的size(参考https://blog.csdn.net/qq_46893497/article/details/113864209) - 当然也有128m左右的文件只启动一个map,但是逻辑十分复杂,我们此时就需要将这个文件合理拆分多个,使
用多个map
任务去完成,配置mr的task数
。 - 还可以开启map端的
推测执行
- 还可以开启
mapjoin
第三,针对mr的shuffle阶段
- 配置
压缩参数
,减少网络输出
- 关联时尽量指定条件,
减少笛卡尔积的产生
- 可以设计分桶表
第四,针对mr的reduce阶段
- 调整适当的redcer数
- 通过设置
每个reducer处理的字节数
,或者task数
,避免小文件过多 - 将distinct换成先group by
- 通过设置
- 使数据尽量均匀分布到各个reduce中
- 启动两个mr,通过参数
skewjoin
,先随机,再聚合 - 对于on中某些key过多,可以加前缀
空值的key变字符串+随机数
分配到不同的reduce中,null关联不上,不影响结果- 还可以开启
reduce端的推测执行
- 启动两个mr,通过参数
第五,针对mr的output阶段
merge参数执行mr结束时合并小文件
- 配置
压缩参数
,减少数据存储空间
第六,针对全局
- 开启mr的
推测执行
- 开启mr的
jvm重用
- 配置压缩
- 开启
并行执行
*********************************以下方向可以深入研究*********************************
配置优化
- SQL的limit的优化
- 执行引擎换spark–查询快
压缩配置优化
- map端输出减少网络传输-是否可切分
- shuffle过程减少网络传输-快
- reduce端输出减少存储空间-压缩比
拉链表使用
分桶
- 分区进一步拆分成桶,获取更高的查询效率
- 不能直接load进去,需要先开启分桶参数,再创建临时表,再insert
并行操作
- 默认只能编译一段HiveSQL,并上锁
- 可以开启并行度,保证可以同时编译,及最大并行度
索引
- 行组索引
- 非等值连接
- 布隆过滤器索引
- 等值连接
小文件的处理
数据倾斜
- 本质:将数据均匀分布到各个reduce中
参数调节
map端预聚合,相当于combiner
- hive.map.aggr=true;
启动两个map job,第一个随机分配map结果,局部聚合;第二个最终聚合
- hive.groupby.skewindata=true;
开启倾斜关联
(运行时/编译时)、开启union的优化
(避免二次读写),并设置判断key倾斜的阈值条数- set hive.optimize.skewjoin=true;
- set hive.optimize.skewjoin.compiletime=true;
- set hive.optimize.union.remove=true;
- set hive.skewjoin.key=100000;默认值100000。
SQL调节
- join
- 将分布均匀的表做为驱动表,
做好列裁剪和过滤
- 表小key集中
- 小表先进内存
- 表大也分桶了但是特殊值过多
空值的key变字符串+随机数分配到不同的reduce中,null关联不上,不影响结果
- 将分布均匀的表做为驱动表,
- group by–维度过小,某些值过多
- count distinct–特殊值过多
- 值为null的单独处理,在union
优化器
SQL优化
- 列值裁剪
- 常量折叠
- 谓词下推
小表
- 启动mapJoin优化,调整mapjoin的size,减少shuffle,默认为20mb,可以调大一些
- set hive.auto.convert.join=true;
- set hive.auto.convert.join.noconditionaltask.size=512000000
- 对mapjoin的原理大概如下:
- 在两个表做join操作的时候,一般会使用两个不通的mapper在join的key上排序然后生成临时文件,reduce使用这些文件作为input,做join操作。当一张表很大,另一张表很小的情况下,不够优。此时会有上千个mapper去读取大表的不同数据,同时这些mapper还需要去hdfs读取小表数据到本地内存,可能会引起性能瓶颈。
- mapjoin的优化在于,在mapreduce task开始之前,创建一个local task, 小表以
hshtable的形式加载到内存
,然后序列化到磁盘,把内存的hashtable压缩为tar文件。然后把文件分发到Hadoop Distributed Cache
,然后传输给每一个mapper,mapper在本地反序列化文件并加载进内存在做join
大表关联中表:
- Bucket-MapJoin开启,一个表的Bucket数是另一个Bucket的整数倍,可以对两个表均做hash再进行join
- set hive.optimize.bucketmapjoin = true;
- 一个表的bucket数是另一个表bucket数的整数倍
- bucket列 == join列
- 必须是应用在map join的场景中
- 如果表不是bucket的,则只是做普通join。
大表关联大表
- SMBJoin开启,基于有序桶表
- set hive.optimize.bucketmapjoin = true;
- set hive.auto.convert.sortmerge.join=true;
- set hive.optimize.bucketmapjoin.sortedmerge = true;
- set hive.auto.convert.sortmerge.join.noconditionaltask=true;
- 小表的bucket数=大表bucket数
- Bucket 列 == Join 列 == sort 列
- 必须是应用在bucket mapjoin 的场景中