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的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 的场景中

猜你喜欢

转载自blog.csdn.net/qq_46893497/article/details/114047447