最近看了尚硅谷的hive高级课程,学有所获,特此与大家分享
hive高级进阶-hive优化+hive执行流程
hive执行流程:
hql语句 -> cliDriver ->Driver
cliDriver:
1.解析客户端-e,-f等参数
2.定义标准输入输出流
3.按照';'划分hql语句
Driver:
1.将HQL语句转换为AST
2.将AST转换为OperationTree
3.将OperationTree转换为TaskTree
4.提交任务执行
Driver包括:
·ParserDriver
1.将HQL语句转换为Token
2.对Token进行解析生成AST
·SemanticAnalyzer
1.将AST转换为QueryBlock
2.将QueryBlock转换为OperationTree
3.对OperationTree进行逻辑优化
4.生成TaskTree
5.TaskTree执行物理优化
·ExecDriver
1.获取MR临时工作目录
2.定义Partitioner
3.定义Mapper和Reducer
4.实例化Job
5.提交Job
hive优化:
hive建表优化:
1.分区表:对应HDFS文件系统上的独立的文件夹,该文件夹下是该分区所有的数据文件
二级分区
动态分区
set hive.exec.dynamic.partition = true
set hive.exec.dynamic.partition.mode = nonstrict
2.分桶表
分区提供一个隔离数据和优化查询的遍历方式。对于一张表或者分区,Hive可以进一步组织成桶,也就是更为细粒度的数据范围划分。
create table stu_buck(id int,name string)
clustered by (id)
into 4 buckets
row format delimited fields terminated by '\t'
注意事项:
1.reduce的个数设置为-1.让job自行决定需要用多少个reduce或者将reduce的个数设置为大于等于分桶表的个数
2.从hdfs中load数据到分桶表,避免本地文件找不到的问题
3.不要使用本地模式
分桶表用途:
1.抽样查询 select * from stu_buck tablesample(bucket 1 out of 4 on id)
2.大表join
3.合适的文件格式
hive支持的存储数据的格式主要有:textfile、sequencefile、orc、parquet
行存储textfile、sequencefile
列存储orc、parquet(以二进制方式存储,不可以直接读取)
列存储的特点:
1.在查询少数几个字段的时候,能大大减少读取的数据量
2.每个字段的数据类型一定是相同的,可以针对性的设计更好的压缩算法
4.合适的压缩格式
deflate
gzip 不支持切分
bzip2 支持切分 压缩后文件大小比较小但是压缩解压缩速度没有lzo快
lzo 支持切分 压缩后没有bzip2小但是压缩和解压缩速度快
snappy 不支持切分,但是压缩和解压缩的速度贼快
HQL语法优化
1.列裁剪和分区裁剪
列裁剪就是查询时只读取需要的列,分区裁剪就是只读取需要的分区,当列很多或者数据量很大时,如果select *
或者不指定分区,全列扫描和全表扫描效率都很低
2.Group By
在map端预聚合 set hive.map.aggr = true
有数据倾斜的时候进行负载均衡 set hive.groupby.mapaggr.checkinterval = true,当该选项设定为true时,生成的查询计划会有两个MR
3.Vectorization:矢量计算
4.多重模式
insert int t_ptn partition(city=A). select id,name,sex, age from student
where city= A;
insert int t_ptn partition(city=B). select id,name,sex, age from student
where city= B;
insert int t_ptn partition(city=c). select id,name,sex, age from student
where city= c;
修改为:
from student
insert int t_ptn partition(city=A) select id,name,sex, age where city= A
insert int t_ptn partition(city=B) select id,name,sex, age where city= B
5.in/exists语句
该语句效率低,推荐使用left semi join替代此语句
select a.id,a.name from a left semi join b on a.id = b.id
6.CBO优化
hive自从0.14.0开始加入cost based optimizer来对hql执行计划进行优化-成本优化器
hive在提供最终执行前,优化每个查询的执行逻辑和物理执行计划。根据查询成本执行进一步的优化,从而产生潜在的不同决策:如何排序连接,执行哪种类型的连接,并行度等
7.谓词下推
将sql语句中的where谓词逻辑尽可能提前执行,减少下游处理的数据量,对应的逻辑优化器是PredicatePushDown
8.MapJoin
将Join双方比较小的表直接分发到各个Map进程的内存中,在Map进程中进行join操作,这样就不用进行Reduce步骤了,从而提高了速度。这样也避免了数据倾斜
9.大表和大表的SMBJoin(Sort Merge Bucket Join)
10.尽量避免笛卡尔积
join时不加on条件或者无效的on条件会导致hive只用一个reducer完成笛卡尔积。
当hive设定为严格模式时,不允许在hql语句中出现笛卡尔积
数据倾斜-绝大部分任务都很快完成,只有一个或者少数几个任务执行的很慢甚至最终执行失败
原因:按照key分组以后,少量的任务负责绝大部分数据的计算,也就是导致数据倾斜的hql中一定存在分组操作
数据倾斜分为单表携带groupby字段的查询和两表(或者多表)join的查询。
单表:
1.使用参数
当任务中有groupby操作同时聚合函数为count或者sum时可以设置参数来处理数据倾斜问题
是否在 Map 端进行聚合,默认为 True
set hive.map.aggr = true;
在 Map 端进行聚合操作的条目数目
set hive.groupby.mapaggr.checkinterval = 100000;
2.增加reduce数量(多个key同时导致数据倾斜)
多表:
1.使用参数
# join 的键对应的记录条数超过这个值则会进行分拆,值根据具体数据量设置
set hive.skewjoin.key=100000;
# 如果是 join 过程出现倾斜应该设置为 true
set hive.optimize.skewjoin=false;
如果开启了,在join过程中hive会将计数超过阈值的倾斜key对应的行临时写进文件中,然后再启动另一个job做map join生成结果
2.mapjoin
hive job优化
·hive map优化:
1.复杂文件增加map数
computeSliteSize(Math.max(minSize,Math.min(maxSize,blocksize)))=blocksize=128M 公式,
调整 maxSize 最大值。让 maxSize 最大值低于 blocksize 就可以增加 map 的个数。
2.小文件合并
在map执行前合并小文件,减少map数:combineHiveInputFormat
set hive.input.format = org.apache.hadoop.hive.ql.io.CombineHiveInputFormat
3.map端聚合
4.推测执行
·hiva reduce优化
1.设置合理的reduce数
reduce并不是越多越好:
1.过多的启动和初始化reduce也会消耗时间和资源
2.reduce过多会输出多个小文件
reduce数目适当且每个reduce处理的数据量也要适当
2.推测执行
3.hive任务整体优化
1.fetch抓取:hive中对某些情况的查询可以不必使用mapreduce计算如:select * from emp
2.本地模式
3.并行执行
4.严格模式-分区表where语句中必须使用分区否则无法执行
使用order必须使用limie过滤
限制笛卡尔积的查询
4.JVM重用