Hive 优化 总结

背景:1.数据倾斜是个问题。

2.map reduce初始化时间长,jobs数较多效率较低,特别是小文件或者开发运算的时候,数据小,但是RM,NM之间的申请,调度和心跳,耗时很长。

核心思想:把Hive SQL 当做Mapreduce程序去优化:hive —> MR,优化了MR,hive执行得更好。

MapReduce简化流程图:




hive 语句执行历史 hive 执行顺序_hive


可以考虑MapReduce流程从左往右优化:

  1. 控制Hive中Map以及Reduce的数量:(根据数据量的大小可以调整reduce数量:正比,map一般不调整)

可以设置split大小,map的数量、reduce任务数量、每个reduce处理的数据量和每个任务最大的reduce数。

到hive方面的优化:

Hive运行方式:使用本地模式(开发&小表小文件---速度快一点)或者集群模式(一般在上线的时候使用)。需要注意的是:

  • hive.exec.mode.local.auto.inputbytes.max默认值为128M
  • 表示加载文件的最大值,若大于该配置仍会以集群方式来运行!
  • 在本地运行,没有提交到hdfs

2.并行计算:当parallel为false时,hive按顺序计算,速度慢一点。注意:hive.exec.parallel.thread.number

  • (一次SQL计算中允许并行执行的job个数的最大值)
  • 并行计算对资源需求大,对服务器压力大。

优化--核心思想--运行模式(本地:数据抓取到本机上运行。集群资源会消耗在提交任务,分配资源,计算时间很短)--并行计算

3.严格模式:防止用户误操作:

查询限制:

  • 对于分区表,必须添加where对于分区字段的条件过滤
  • 限制执行笛卡尔积的查询(数据大的俩表笛卡尔积,变得更复杂)。

4.Hive排序:适当选择排序方式:

  • Order By - 对于查询结果做全排序,只允许有一个reduce处理(当数据量较大时,应慎用。严格模式下,必须结合limit来使用)
  • Sort By - 对于单个reduce的数据进行排序(只保障每个reduce中数据的排序,reduce之间的排序无法保障)
  • Distribute By - 分区排序,经常和Sort By结合使用(map分发数据时,按照分区进行分发到reduce中)
  • Cluster By - 相当于 Sort By + Distribute By注意:(Cluster By不能通过asc、desc的方式指定排序规则;(有默认的排序规则)可通过 distribute by column sort by column asc|desc 的方式)

5.Hive Join:

1.Join计算时,将小表(驱动表)放-在join的左边(目的:提高效率;把shuffle和reduce去掉,只留下split和map,小表数据放内存,大表逐条读取,匹配到map输出)

Map Join:在Map端完成Join:

SQL方式,在SQL语句中添加MapJoin标记(mapjoin hint)

语法:

SELECT /+ MAPJOIN(smallTable) / smallTable.key, bigTable.value

FROM smallTable JOIN bigTable ON smallTable.key = bigTable.key;

2.自动的mapjoin:

设置mapjoin相关参数

6.Map-Side聚合:count等UDF函数在数据量大的情况下,效率较低:

通过设置配置参数开启在Map端的聚合:并不是所有的聚合都是在Map端完成,例如:1万条聚合后为9千条,效果不明显,就没有必要再map聚合。(如何提前知道聚合效果:map一次可以抓取1万条数据,先聚合一次,拿结果和配置条件对比)

7.Hive - JVM重用:小文件个数过 和(或者) task个数过多:

  • 原因:每处理一个小文件或者没调用一个task,虽然计算时间短,但是申请和释放时间长。处理:先申请一部分jvm资源,就不用重复申请,处理一个接着下一个。所有任务全部处理完后才会释放这部分资源
  • 通过 set mapred.job.reuse.jvm.num.tasks=n; 来设置。(n为task插槽个数)
  • 缺点:设置开启之后,task插槽会一直占用资源,不论是否有task运行,直到所有的task即整个job全部执行完成时,才会释放所有的task插槽资源!