核心思想:把Hive SQL当作Mapreduce程序去优化
以下SQL不会转成Mapreduce来执行
- select仅查询本表字段
- where仅对本表字段做条件过滤
Explanin 显示执行计划
explain [extended] query_sql;
-- extended 显示更详细
Hive运行方式
- 本地模式
- 集群模式
开启本地模式
计算任务 小 时:
set hive.exec.mode.local.auto=true;
注意:
hive.exec.mode.local.inputbytes.max
-- 默认值为128M
-- 表示加载文件的最大值,若大于改配置值仍会以集群方式运行
并行计算
开启并行计算模式
set hive.exec.parallel=true;
注意:
hive.exec.parallel.thread.number
-- 一次计算中允许并行执行的job个数的最大值
严格模式
set hive.mapred.mode=strict;
-- 默认为 nonstict非严格模式
查询限制
1、对于分区表,必须添加where对于分区字段的条件过滤
2、order by语句必须包含limit输出限制
3、限制执行笛卡尔积的查询
Hive排序
order by
对于查询结果做全排序,只允许有一个reduce处理
当数据量较大时,应慎用,严格模式下必须结合limit来使用
sort by
对单个reduce的数据进行排序
sort by不是全局排序,其在数据进入reducer前完成排序,因此,如果用sort by进行排序,并且设置mapred.reduce.tasks>1,则sort by只会保证每个reducer的输出有序,并不保证全局有序。
sort by不同于order by,它不受hive.mapred.mode属性的影响,sort by的数据只能保证在同一个reduce中的数据可以按指定字段排序。使用sort by你可以指定执行的reduce个数(通过set mapred.reduce.tasks=n来指定),对输出的数据再执行归并排序,即可得到全部结果。
distribute by
distribute by是控制在map端如何拆分数据给reduce端的。hive会根据distribute by后面列,对应reduce的个数进行分发,默认是采用hash算法。
sort by为每个reduce产生一个排序文件。在有些情况下,你需要控制某个特定行应该到哪个reducer,这通常是为了进行后续的聚集操作。distribute by刚好可以做这件事。因此,distribute by经常和sort by配合使用。
注:Distribute by和sort by的使用场景
1.Map输出的文件大小不均。
2.Reduce输出文件大小不均。
3.小文件过多。
4.文件超大。
cluster by
相当于 sort by + distribute by
cluster by 不能 通过asc desc的方式指定排序规则,排序只能是倒序排序
可通过 distribute by column sort by column asc|desc 的方式
Hive Join
1. Join计算时,将小表(驱动表)放在join的左遍
2. Map join: 在Map端完成join
两种方式
1、SQL方式,在SQL语句中添加MapJoin标记
语法:
select /*+ mapjoin(smallTbl) */ smallTbl.key,bigTbl.value
from smallTbl join bigTbl on smallTbl.key = bigTbl.key;
2、开启自动的MapJoin
set hive.auto.convert.join=true;
-- 该参数为true,hive自动对左边的表统计量,如果时小表就加入内存,即对小表mapjoin
相关参数
hive.mapjoin.smalltable.filesize
-- 大表小表判断的阈值,如果表的大小小于该值就会被加载到内存
hive.ignore.mapjoin.hint
-- 默认值true,是否忽略mapjoin hint即sql中的mapjoin标记
hive.auto.convert.join.noconditionnoltask
-- 默认值true,将普通的join转化为普通的mappjoin时,是否将对各mapjoin转化为一个mapjoin
hive.auto.convert.join.onconditionaltask.size
-- 将多个mapjoin转化为一个mapjoin时,其表的最大值
Map-side聚合
set hive.map.aggr=true;
相关参数
hive.groupby.mapaggr.checkinterval
-- map端group by 执行聚合时处理多少行数据(默认100000)
hive.map.aggr.hash.min.reduction
-- 进行聚合的最小比例
-- 预先对100000条数据做聚合,若聚合之后的 数据量/100000 的值大于改配置的0.5,则不会聚合
hive.map.aggr.hash.percentmemory
-- map端聚合的内存使用最大值
hive.map.aggr.hash.force.flush.memory.threshold
-- map端聚合的hash表最大可用内容,大于该值则会出发flush
hive.groupby.skewindata
-- ** 是否对groupby产生的数据倾斜做优化,默认false
-- (两次mapreduce)
控制hive中map和reduce的数量
map数量相关参数
mapred.max.split.size
-- 一个split的最大值,即每个map处理文件的最大值
mapre.min.split.size.per.node
-- 一个节点上split的最小值
mapred.min.split.size.per.rack
-- 一个机架上split的最小值
reduce数量相关参数
mapred.reduce.tasks
-- 强制指定reduce任务的数量
hive.exec.reduces.bytes.per.reducer
-- 每个reduce任务处理的数据量
hive.exec.reducers.max
-- 每个任务最大的reduce数量
JVM重用
类似线程池
使用场景:
1、小文件过多
2、task个数过多
set mapred.job.reuse.jvm.num.tasks=n;
-- n为task插槽个数
缺点:设置后,task插槽会一直占用资源,无论是否有task执行
知道所有task即整个job全部执行完成后,才会释放所有task插槽资源