本节介绍基于MR 执行引擎的常用调优手段,包括 Join 优化、数据倾斜处理、MR 作业资源调优、小文件优化、压缩以及并行执行等。
Join 优化
1、MapJoin(小表 Join 大表):开启 hive.auto.convert.join=true 后,Hive 会基于输入文件大小自动将普通 Join 转为 MapJoin,将小表加载进内存在 Map 端完成关联,避免 Shuffle 过程;小表阈值由 hive.mapjoin.smalltable.filesize 控制;
2、大表 Join 大表:关联键存在大量相同值时容易产生数据倾斜,可先对空 key 或异常 key 进行过滤,或将空 key 转换为随机值打散;
3、关联查询中多次使用同一张表时,合理设计中间结果,减少重复扫描。
数据倾斜处理
1、group by 倾斜:设置 hive.groupby.skewindata=true,查询会拆分为两个 MR 作业,第一个作业随机打散 key 预聚合,第二个作业完成最终聚合;
2、count(distinct) 倾斜:改为先按 key 进行 group by,再 count 的两段式写法;
3、大小表关联:优先使用 MapJoin;
4、空值处理:关联前过滤空 key,或使用 rand() 打散。
MR 作业资源调优
MR 作业的内存与并行度可通过如下参数调整(可在会话级通过 set 命令设置):
| 参数名称 | 说明 |
|---|---|
| mapreduce.map.memory.mb | Map 任务申请的容器内存大小 |
| mapreduce.reduce.memory.mb | Reduce 任务申请的容器内存大小 |
| mapreduce.map.java.opts | Map 任务 JVM 堆内存,建议为容器内存的80%左右 |
| mapreduce.reduce.java.opts | Reduce 任务 JVM 堆内存,建议为容器内存的80%左右 |
| hive.exec.reducers.bytes.per.reducer | 每个Reduce 处理的数据量,默认256000000(约256MB),用于计算Reduce个数 |
| hive.exec.reducers.max | Reducer 的最大个数,默认1009 |
| mapred.min.split.size | Map 输入分片最小值,调大可减少Map任务数 |
| mapred.max.split.size | Map 输入分片最大值,调小可增加Map任务数 |
小文件优化
1、开启小文件合并:hive.merge.mapfiles=true(只有Map任务的作业)、hive.merge.mapredfiles=true(含Reduce的作业),任务结束后合并小文件;
2、hive.merge.size.per.task 控制每个合并任务的目标文件大小,默认 256000000;
3、ORC 表可定期执行 ALTER TABLE <表名> CONCATENATE 合并小文件;
4、控制动态分区写入,避免一次性生成大量小文件。
压缩
1、中间结果压缩:hive.exec.compress.intermediate=true,并配置 mapreduce.map.output.compress.codec,减少 Shuffle 传输量;
2、最终输出压缩:hive.exec.compress.output=true;
3、建表时优先使用 ORC/Parquet 列式存储,并通过 TBLPROPERTIES 指定压缩算法,例如 ('orc.compress'='SNAPPY')。
并行执行与向量化
1、hive.exec.parallel=true:一个 SQL 中互不依赖的子查询可以并行执行,减少总执行时间;
2、hive.vectorized.execution.enable=true:开启向量化执行,按批处理数据行,提升 MR 作业的 CPU 效率。
常用服务端配置参数
以下为集群Hive 服务常用配置参数(hive-site.xml),供用户了解服务端行为:
| 参数名称 | 参数说明 | 默认值 |
| hive.server2.thrift.min.worker.threads | HiveServer 内部线程池初始化时启动的线程数量。 | 5 |
| hive.metastore.server.min.threads | MetaStore 启动的用于处理连接的线程数,如果超过设置的值之后,MetaStore 就会一直维护不低于设定值的线程数,即常驻 MetaStore 线程池的线程会维护在指定值之上。 | 200 |
| hive.exec.reducers.max | Hive 提交的 MapReduce 任务中 Reducer 的最大个数。 | 1009 |
| hive.server2.thrift.max.worker.threads | HiveServer 内部线程池最大能启动的线程数量。 | 500 |
| hive.default.fileformat | Hive 使用的默认文件格式,支持 TextFile、SequenceFile、RCFile、ORC 和 parquet 格式。 | parquet |
| hive.auto.convert.join | Hive 基于输入文件大小将普通 join 转为 mapjoin 的开关 | true |
| hive.server2.enable.doAs | HiveServer2 在与其他服务(如 Yarn、HDFS 等)会话时是否模拟客户端用户。如果将此配置项从false修改为true,会导致只有列权限的用户访问相应表权限缺失。 | true |
| javax.jdo.option.ConnectionDriverName | JDBC元存储库的驱动程序类名称 | com.mysql.jdbc.Driver |
| hive.users.in.admin.role | 用逗号分隔的用户列表,将在元存储启动时添加到ADMIN角色 | hive |
| hive.server2.thrift.port | HiveServer2 Thrift 接口的端口号 | 10000 |
| hive.server2.webui.enable.cors | 跨域设置 | true |
| hive.support.concurrency | Hive是否支持并发 | false |
| hive.metastore.connect.retries | 客户端建立与metastore连接时的重试次数 | 10 |
| hive.metastore.db.type | metastore类型 | MYSQL |
| hive.exec.compress.output | 控制hive的查询结果输出是否进行压缩 | true |
| hive.exec.dynamic.partition | 是否开启动态分区 | true |
| hive.exec.max.dynamic.partitions | 在所有执行MR的节点上,最大一共可以创建多少个动态分区 | 5000 |