具体细节见前文Hive调优和原理篇

四大调优方向

1 建表设计层面
2 HQL语法和运行参数层面
3 HIVE架构层面
4 HIVE数据倾斜

一 建表设计层面

谈分区分桶表,如join字段可以用分桶表。
合理的文件格式,
输出结果/中间结果数据压缩
位数组,列式存储优化存储方式

二 HQL语法和运行参数层面

10万+数量一个reducetask足够,合理设计task并行度
修改map数据最小最大分割大小,可以合理调整map task并行度。但直接修改map tasks参数没有效果

主动开启列裁剪,只读需要的列

合并小文件:map输入数据有两种方式(一种合并小文件默认128mb,一种不合并文件)

join的优化:
1 小表无脑用mapjoin,小表数据分发存入各节点内存中,map阶段直接join,默认内存25mb
2 join的数据倾斜可以用skewjoin,根据skewjoin设置的参数阈值拆分大key,默认10万。
3 主动开启谓词下推,where提前执行减少下游处理量。如join x where x,会改成先where条件过滤后再join
4 (建表层面:分桶也可以提高join效率)
5 CBO成本优化器,照执行成本最小的来选择合适的join算法
6 随机id打散大表:大表加随机数id如1-4,小表数据扩容成4倍文件并各自加上id 1-4。
之后大表和小表通过id join,就可以把1个reduceTask变成4个redcueTask,修改提高并行执行参数(默认8)

groupby优化:
map端设定行数阈值拆分job做预聚合,然后最终大合并
主动开启map预聚合两个参数:1 参数true开启 2 map端行数阈值则拆分map聚合job

order by/count/distinct优化:
一个job sql可以拆分多个job执行,如count(distinct),因为distinct去重只有一个reduce task,可改为先group by后再count(1)
如count (distinct a)group by b可以改成先group by a,b然后group by b,最后直接count a。另外可以设置参数自动拆分distinct

in/exist 语法改写 semi join,也可以用布隆过滤器判断数据是否在表中
union:grouping sets代替union,多次读表变一次读

三 HIVE架构层面

1 select *等不涉及计算可以不调用mr,直接hive主动开启本地抓取模式
2 JVM重用,可改参数由一个jvm执行一个task改成一个jvm串行复用的执行多个个task
3 并行执行
随机id打散大表:大表加随机数id如1-4,小表数据扩容成4倍文件并各自加上id 1-4。
之后大表和小表通过id join,就可以把1个reduceTask变成4个redcueTask,提高并行执行性能
4 推测执行,根据一定法则推测出性能低下的task,给这种task多执行一个备份task,最后取运算最快的task结果
5 严格模式

四 Hive实现原理

1 join
select a.age from a join b on a.id = b.id
遍历a表id为key,age+1为value,map局部预合并age+数量为value。遍历b表同理,最后通过id为key进行shuffle和reduce合并并解析为需要的结果
2 groupby key a,key b
局部<a,b> 为key,如求count时则key出现的数量为value,最后全局汇总
3 exists/case when/where/having等就是if else过滤
4 distinct
通过groupby分组聚合,也有hash去重的实现方式

额外的记录

count计数的聚合模式

·count(列):如果列中有null值,那么这一列不会被记入统计的行数。
另外,Hive读取数据进行计算时,需要将字节流转化为对象的序列化和反序列化的操作。

·count(*):不会出现count(列)在行是null值的情况下,不计入行数的问题。
另外,count(*)在进行数据统计时不会读取表中的数据,只会使用到HDFS文件中每一行的行偏移量。
该偏移量是数据写入HDFS文件时,HDFS添加的。

·count(1):
count(*)也包含NULL,如果表没有主键,那么count(1)比count(*)快。
表有主键,count(*)会自动优化到主键列上。如果表只有一个字段,count(*)最快。
count(1)跟count(主键)一样,只扫描主键。count(*)跟count(非主键)一样,扫描整个表。明显前者更快一些。
count(1)和count(*)基本没有差别,但在优化的时候尽量使用count(1)

udf、udaf、udtf函数定义与用法

(1)UDF(user-defined function)作用于单个数据行,产生一个数据行作为输出。(数学函数,字符串函数)
(2)UDAF(用户定义聚集函数 User- Defined Aggregation Funcation):接收多个输入数据行,并产生一个输出数据行。(count,max)
(3)UDTF(表格生成函数 User-Defined Table Functions):接收一行输入,输出(explode)

总结:
UDF:返回对应值,一对一  
UDAF:返回聚类值,多对一
UDTF:返回拆分值,一对多

行转列:

select 分类字段,concat_ws(',',collect_set(合并字段))  as 别名 from table_name group 分类字段;

列转行:

select  字段,字段别名  from table_name lateral view explode(split(拆分字段,分隔符))表别名 as 字段别名;