Hive 优化 总结
背景:1.数据倾斜是个问题。
2.map reduce初始化时间长,jobs数较多效率较低,特别是小文件或者开发运算的时候,数据小,但是RM,NM之间的申请,调度和心跳,耗时很长。
核心思想:把Hive SQL 当做Mapreduce程序去优化:hive —> MR,优化了MR,hive执行得更好。
MapReduce简化流程图:
可以考虑MapReduce流程从左往右优化:
- 控制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插槽资源!