Hive学习笔记(4)——调优
常用参数设置
set mapred.recduce.tasks = 1;
:设置默认启动的Reducer数量。set hive.mapred.mode = strict/nonstrict;
:开启严格模式,如果设置为strict
,会禁止以下情况提交任务,以防止触发低效的MapReduce任务:- 笛卡尔积
JOIN
; ORDER BY
不含LIMIT
;- 读取分区表没有指定分区字段。
- 笛卡尔积
set hive.merge.mapredfiles = true;
:在map任务开始和Reduce任务结束时合并小文件,防止开启过多的map任务。set hive.merge.size.per.task = 256000000;
:每个任务合并后文件的大小,据此大小确定Reducer的个数。set hive.merge.smallfiles.avgsize=64000000;
:需要合并的小文件群的平均大小。set hive.exec.compress.intermediate = true;
:开启中间压缩,减少job中Map和Reduce Task的数据传输量。set hive.exec.mode.local.auto = true;
:开启本地模式,可以在处理小数据集时避免使用MapReduce。set hive.exec.dynamic.partition = true;
:打开动态分区,默认关闭。set hive.exec.dynamic.partition.mode = strict/nonstrict;
:动态分区若采用严格模式,则至少要包含一个静态分区。
存储和压缩方式
- 行式存储:数据按行连续存储,行查询效率高、列查询效率低,适合
SELECT *
比较多的情况,数据压缩效率低。默认的TextFile
和SequenceFile
均为行式存储。 - 列式存储:数据按列连续存储,列查询效率高、行查询效率低,适合
SELECT col_name
比较多的情况,数据压缩效率高。ORCFile
和Parquet
为列式存储。 - 压缩方式:Hive支持多种压缩方式,如
Snappy
、LZ4
、LZO
、GZIP
、BZIP2
等。压缩数据能减少磁盘空间占用、降低网络IO和磁盘IO,提升传输速度。
在实际项目开发中,Hive表存储格式一般选择ORCFile
或Parquet
,压缩方式一般选择Snappy
。
Hive查看执行计划
EXPLAIN [EXTENDED]
可以查看Hive如何把任务转化为MapReduce任务:
- 显示抽象语法树
AST
; - 显示STAGE依赖关系:一个Hive任务包含多个STAGE,不同STAGE之间存在依赖关系,越复杂的任务会包含越多的STAGE,需要更多的时间完成;
- 显示每个阶段的具体描述,例如
SelectOperator
、GroupByOperator
及其对应的字段名称。
数据倾斜
分布式数据处理希望数据平均分布到每个处理节点,但是由于数据本身或者分布算法的问题,每个节点分配到的数据量不均衡,导致分布式处理的性能大打折扣。
解决GROUP BY的数据倾斜
set hive.map.aggr = true;
开启Map端聚合参数设置。set hive.groupby.skewindata = true;
开启负载均衡,默认关闭。- 开启负载均衡,会产生两个MapReduce任务,第一个MapReduce Job会把Map输出的结果随机分配到Reduce中,达到负载均衡的目的;第二个MapReduce Job根据预处理的数据结果按照
GROUP BY
键分布到Reduce中,保证相同的键分布到同一个Reduce中,完成聚合操作。
解决COUNT DISTINCT的数据倾斜
- 由于需要去重,会把Map阶段的输出分布到一个Reduce Task上,因此可以转化为先
GROUP BY
去重、再COUNT(1)
的方式来优化。
JOIN优化
- 多表连接使用同一个字段,Hive会进行优化,把多表连接在一个Map/Reduce上进行:假定最后一个表是最大的表,将前面的表缓存起来,扫描到最后的表再进行计算。因此需要保证查询的表从左到右依次增大。也可以通过
/*+STREAMTABLE()*/
来标识最大的表。
大表JOIN小表优化
set hive.auto.convert.join = true;
开启mapjoin功能,默认是开启的。- mapjoin hint:
/*+MAPJOIN(b)*/
(mapjoin多个表:/*+MAPJOIN(b, c, d)*/
)。 - 在Map阶段进行
JOIN
,把小表全量复制到每个Map节点的内存中,在Map中完成JOIN,无需Reduce过程,因此不会产生数据倾斜。 - 通过设置
set hive.auto.convert.join.noconditionaltask.size
来确定小表的大小是否满足条件,默认25MB,一般不能超过1GB。
大表JOIN大表优化
- 方法1:根据业务需求,限制行数、列数,使得过滤后的表满足mapjoin的条件。
- 方法2:针对NULL值过多造成的数据倾斜,对NULL值取随机数,随机分发到不同的Reducer上。
- 方法3:倍数B表,再取模
JOIN
。 - 方法4:动态一分为二,不倾斜的正常
JOIN
,倾斜的找出来后mapjoin,然后UNION ALL
。
其他
- 尽量不使用
SELECT *
,用到哪些列指定哪些列。 WHERE
尽量添加过滤条件,去掉无关的数据行。- 输入文件不要是大量的小文件,否则开启过多的Map节点造成性能上的浪费。