在企业中应用 Hive 构建离线数仓是一种非常广泛的计划。只管 Hive 的应用场景是通过批处理的形式解决大数据,通常对解决工夫不敏感。然而在资源无限的状况下,咱们须要关注 Hive 的性能调优,从而不便数据的疾速产出。同时,对于 Hive 的性能调优,也是面试中比拟常见的问题,因而把握 Hive 性能调优的一些办法,不仅可能在工作中晋升效率而且还能够在面试中怀才不遇。本文会通过四个方面介绍 Hive 性能调优,次要包含:
- 性能调优的工具
- 设计优化
- 数据存储优化
- 作业优化
性能调优的工具
HQL 提供了两个查看查问性能的工具:explain与analyze,除此之外 Hive 的日志也提供了十分具体的信息,不便查看执行性能和报错排查。
善用 explain 语句
explain 语句是查看执行打算常常应用的一个工具,能够应用该语句剖析查问执行打算,具体应用语法如下:
EXPLAIN [FORMATTED|EXTENDED|DEPENDENCY|AUTHORIZATION] hql_query
下面的执行语句中,有 4 个可选的关键字,其具体含意如下:
- FORMATTED:对执行打算进行格式化,返回 JSON 格局的执行打算
- EXTENDED:提供一些额定的信息,比方文件的门路信息
- DEPENDENCY:以 JSON 格局返回查问所依赖的表和分区的列表,从 Hive0.10 开始应用,如下图
- AUTHORIZATION:列出须要被受权的条目,包含输出与输入,从 Hive0.14 开始应用, 如下图
一个典型的查问执行打算次要包含三局部,具体如下:
- Abstract Syntax Tree (AST):形象语法树,Hive 应用一个称之为 antlr 的解析生成器,能够主动地将 HQL 生成为形象语法树
- Stage Dependencies:会列出运行查问所有的依赖以及 stage 的数量
- Stage Plans:蕴含了十分重要的信息,比方运行作业时的 operator 和 sort orders
举个栗子
假如有一张表:
CREATE TABLE employee_partitioned
(
name string,
work_place ARRAY<string>,
gender_age STRUCT<gender:string,age:int>,
skills_score MAP<string,int>,
depart_title MAP<STRING,ARRAY<STRING>>
)
PARTITIONED BY (Year INT, Month INT)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '|'
COLLECTION ITEMS TERMINATED BY ','
MAP KEYS TERMINATED BY ':';
查看执行打算:
EXPLAIN
SELECT gender_age.gender,
count(*)
FROM employee_partitioned
WHERE YEAR=2020
GROUP BY gender_age.gender
LIMIT 2;
执行打算概览:
如上图:Map/Reduce operator tree是形象语法树 AST 局部;**STAGE
DEPENDENCIES包含三个阶段:Stage-0、Stage- 1 及 Stage-2,其中 Stage-0 是 root stage,即 Stage- 1 与 Stage- 2 依赖于 Stage-0;STAGE PLANS** 局部,Stage- 1 与 Stage2 都蕴含一个 Map Operator Tree 和一个 Reduce Operator Tree,Stage- 0 不蕴含 map 和 reduce,仅仅是一个 fetch 数据的操作。
执行打算详细信息:
STAGE DEPENDENCIES:
Stage-1 is a root stage
Stage-2 depends on stages: Stage-1
Stage-0 depends on stages: Stage-2
STAGE PLANS:
Stage: Stage-1
Map Reduce
Map Operator Tree:
TableScan
alias: employee_partitioned
filterExpr: (year = 2020) (type: boolean)
Statistics: Num rows: 1 Data size: 227 Basic stats: PARTIAL Column stats: NONE
Select Operator
expressions: gender_age (type: struct<gender:string,age:int>)
outputColumnNames: gender_age
Statistics: Num rows: 1 Data size: 227 Basic stats: PARTIAL Column stats: NONE
Reduce Output Operator
key expressions: gender_age.gender (type: string)
sort order: +
Map-reduce partition columns: rand() (type: double)
Statistics: Num rows: 1 Data size: 227 Basic stats: PARTIAL Column stats: NONE
Reduce Operator Tree:
Group By Operator
aggregations: count()
keys: KEY._col0 (type: string)
mode: partial1
outputColumnNames: _col0, _col1
Statistics: Num rows: 1 Data size: 227 Basic stats: COMPLETE Column stats: NONE
File Output Operator
compressed: false
table:
input format: org.apache.hadoop.mapred.SequenceFileInputFormat
output format: org.apache.hadoop.hive.ql.io.HiveSequenceFileOutputFormat
serde: org.apache.hadoop.hive.serde2.lazybinary.LazyBinarySerDe
Stage: Stage-2
Map Reduce
Map Operator Tree:
TableScan
Reduce Output Operator
key expressions: _col0 (type: string)
sort order: +
Map-reduce partition columns: _col0 (type: string)
Statistics: Num rows: 1 Data size: 227 Basic stats: COMPLETE Column stats: NONE
value expressions: _col1 (type: bigint)
Reduce Operator Tree:
Group By Operator
aggregations: count(VALUE._col0)
keys: KEY._col0 (type: string)
mode: final
outputColumnNames: _col0, _col1
Statistics: Num rows: 1 Data size: 227 Basic stats: COMPLETE Column stats: NONE
Limit
Number of rows: 2
Statistics: Num rows: 1 Data size: 227 Basic stats: COMPLETE Column stats: NONE
File Output Operator
compressed: false
Statistics: Num rows: 1 Data size: 227 Basic stats: COMPLETE Column stats: NONE
table:
input format: org.apache.hadoop.mapred.TextInputFormat
output format: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat
serde: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe
Stage: Stage-0
Fetch Operator
limit: 2
Processor Tree:
ListSink
巧用 analyze 语句
analyze 语句能够收集一些具体的统计信息,比方表的行数、文件数、数据的大小等信息。这些统计信息作为元数据存储在 hive 的元数据库中。Hive 反对表、分区和列级别的统计 (与 Impala 相似),这些信息作为 Hive 基于老本优化策略(Cost-Based Optimizer (CBO)) 的输出, 该优化器的次要作用是抉择消耗最小系统资源的查问打算。其实,在 Hive3.2.0 版本中,能够主动收集这些统计信息,当然也能够通过 analyze 语句进行手动统计表、分区或者字段的信息。具体的应用形式如下:
- 1. 收集表的统计信息(非分区表),当指定 NOSCAN 关键字时,会疏忽扫描文件内容,仅仅统计文件的数量与大小,速度会比拟快
-- 不应用 NOSCAN 关键字
hive> ANALYZE TABLE user_behavior COMPUTE STATISTICS;
...
Table default.user_behavior stats: [numFiles=1, numRows=10, totalSize=229, rawDataSize=219]
Time taken: 23.504 seconds
-- 应用 NOSCAN 关键字
hive> ANALYZE TABLE user_behavior COMPUTE STATISTICS NOSCAN;
Table default.user_behavior stats: [numFiles=1, numRows=10, totalSize=229, rawDataSize=219]
Time taken: 0.309 seconds
- 2. 收集分区表的统计信息
-- 收集具体分区的统计信息
hive> ANALYZE TABLE employee_partitioned PARTITION(year=2020, month=06) COMPUTE STATISTICS;
...
Partition default.employee_partitioned{year=2020, month=06} stats: [numFiles=1, numRows=0, totalSize=227, rawDataSize=0]
Time taken: 19.283 seconds
-- 收集所有分区的统计信息
hive> ANALYZE TABLE employee_partitioned PARTITION(year, month) COMPUTE STATISTICS;
...
Partition default.employee_partitioned{year=2020, month=06} stats: [numFiles=1, numRows=0, totalSize=227, rawDataSize=0]
Time taken: 17.528 seconds
- 3. 收集表的某个字段的统计信息
hive> ANALYZE TABLE user_behavior COMPUTE STATISTICS FOR COLUMNS user_id ;
尖叫提醒:
能够通过设置:SET hive.stats.autogather=true,进行主动收集统计信息,对于 INSERT OVERWRITE/INTO 操作的表或者分区,能够主动收集统计信息。值得注意的是,LOAD 操作不可能主动收集统计信息
一旦这些统计信息收集结束,能够通过 DESCRIBE EXTENDED/FORMATTED 语句查问统计信息,具体应用如下:
-- 查看一个分区的统计信息
hive> DESCRIBE FORMATTED employee_partitioned PARTITION(year=2020, month=06);
...
Partition Parameters:
COLUMN_STATS_ACCURATE true
numFiles 1
numRows 0
rawDataSize 0
totalSize 227
transient_lastDdlTime 1591437967
...
-- 查看一张表的统计信息
hive> DESCRIBE FORMATTED employee_partitioned;
...
Table Parameters:
numPartitions 1
transient_lastDdlTime 1591431482
...
-- 查看某列的统计信息
hive> DESCRIBE FORMATTED user_behavior.user_id;
罕用日志剖析
日志提供了 job 运行的详细信息,通过查看日志信息,能够剖析出导致作业执行瓶颈的问题,次要包含两种类型的日志:系统日志和作业日志。
系统日志蕴含了 Hive 运行时的状态等信息,能够通过{HIVE_HOME}/conf/hive-log4j.properties 文件进行配置,次要的配置选项有:
hive.root.logger=WARN,DRFA ## 日志级别
hive.log.dir=/tmp/${user.name} ## 日志门路
hive.log.file=hive.log ## 日志名称
也能够通过 Hive cli 命令行设置日志级别:$hive --hiveconf hive.root.logger=DEBUG,console
这种形式只能在以后会话失效。
作业日志所蕴含的作业信息通常是由 YARN 治理的,能够通过 yarn logs -applicationId <application_id>
命令查看作业日志。
设计优化
分区表
对于一张比拟大的表,将其设计成分区表能够晋升查问的性能,对于一个特定分区的查问,只会加载对应分区门路的文件数据,所以执行速度会比拟快。值得注意的是,分区字段的抉择是影响查问性能的重要因素,尽量避免层级较深的分区,这样会造成太多的子文件夹。一些常见的分区字段能够是:
- 日期或者工夫
比方 year、month、day 或者 hour,当表中存在工夫或者日期字段时,能够应用些字段。
- 地理位置
比方国家、省份、城市等
- 业务逻辑
比方部门、销售区域、客户等等
分桶表
与分区表相似,分桶表的组织形式是将 HDFS 上的文件宰割成多个文件。分桶能够放慢数据采样,也能够晋升 join 的性能(join 的字段是分桶字段),因为分桶能够确保某个 key 对应的数据在一个特定的桶内(文件),所以奇妙地抉择分桶字段能够大幅度晋升 join 的性能。通常状况下,分桶字段能够抉择常常用在过滤操作或者 join 操作的字段。
索引
创立索引是关系型数据库性能调优的常见伎俩,在 Hive 中也不例外。Hive 从 0.7 版本开始反对索引,应用索引相比全表扫描而言,是一种比拟便宜的操作,Hive 中创立索引的形式如下:
CREATE INDEX idx_user_id_user_behavior
ON TABLE user_behavior (user_id)
AS 'COMPACT'
WITH DEFERRED REBUILD;
下面创立的是 COMPACT 索引,存储的是索引列与其对应的 block id 的 pair 对。除了此种索引外,Hive 还反对位图索引(BITMAP), 应用形式如下:
CREATE INDEX idx_behavior_user_behavior
ON TABLE user_behavior (behavior)
AS 'BITMAP'
WITH DEFERRED REBUILD;
下面创立的索引时,应用了 WITH DEFERRED REBUILD
选项,该选项能够防止索引立刻被创立,当建设索引时,能够应用 LTER...REBUILD
命令 (见上面的示例),值得注意的是:当基表(被创立索引的表) 发生变化时,该命令须要被再次执行以便更新索引到最新的状态。
ALTER INDEX idx_user_id_user_behavior ON user_behavior REBUILD;
一旦索引创立胜利,会生成一张索引表,表的名称格局为:数据库名__表名_索引名__
,能够应用上面的命令查看索引:
hive> SHOW TABLES '*idx*';
OK
default__user_behavior_idx_user_id_user_behavior__
Time taken: 0.044 seconds, Fetched: 1 row(s)
索引表蕴含索引列、HDFS 的文件 URI 以及每行的偏移量,能够通过上面命令查看:
-- 查看索引表构造
hive> DESC default__user_behavior_idx_user_id_user_behavior__;
OK
user_id int
_bucketname string
_offsets array<bigint>
Time taken: 0.109 seconds, Fetched: 3 row(s)
-- 查看索引表内容
hive> SELECT * FROM default__user_behavior_idx_user_id_user_behavior__;
OK
9 hdfs://cdh03:8020/user/hive/warehouse/user_behavior/userbehavior.csv [181]
7 hdfs://cdh03:8020/user/hive/warehouse/user_behavior/userbehavior.csv [136]
1 hdfs://cdh03:8020/user/hive/warehouse/user_behavior/userbehavior.csv [0]
6 hdfs://cdh03:8020/user/hive/warehouse/user_behavior/userbehavior.csv [113]
5 hdfs://cdh03:8020/user/hive/warehouse/user_behavior/userbehavior.csv [90]
10 hdfs://cdh03:8020/user/hive/warehouse/user_behavior/userbehavior.csv [205]
4 hdfs://cdh03:8020/user/hive/warehouse/user_behavior/userbehavior.csv [66]
8 hdfs://cdh03:8020/user/hive/warehouse/user_behavior/userbehavior.csv [158]
3 hdfs://cdh03:8020/user/hive/warehouse/user_behavior/userbehavior.csv [44]
2 hdfs://cdh03:8020/user/hive/warehouse/user_behavior/userbehavior.csv [22]
Time taken: 0.28 seconds, Fetched: 10 row(s)
如果要删除索引,能够应用 DROP INDEX 命令,如下:
DROP INDEX idx_user_id_user_behavior ON user_behavior;
应用 skewed/temporary 表
Hive 除了能够应用外部表、内部表、分区表、分桶表之外,也能够应用 skewed/temporary 表,也能够在肯定水平上晋升性能。
Hive 从 0.10 版本之后开始反对 skewed 表,该表能够缓解数据歪斜。这种表之所以可能晋升性能,是因为能够主动将造成数据歪斜的数据宰割成不同的文件或者门路。应用示例如下:
CREATE TABLE sample_skewed_table (
dept_no int,
dept_name string
)
SKEWED BY (dept_no) ON (1000, 2000);-- 指定数据歪斜字段
另外,还能够应用 temporary 长期表,将公共应用局部的数据集建成长期表,同时长期表反对 SSD 或 memory 的数据存储,从而能够晋升性能。
数据存储优化
文件格式
Hive 反对 TEXTFILE, SEQUENCEFILE, AVRO, RCFILE, ORC, 以及 PARQUET 文件格式,能够通过两种形式指定表的文件格式:
- CREATE TABLE … STORE AS <file_format>: 即在建表时指定文件格式,默认是 TEXTFILE
- ALTER TABLE … [PARTITION partition_spec] SET FILEFORMAT <file_format>: 批改具体表的文件格式
一旦存储文件格式为 TEXT 的表被创立,能够间接通过 load 命令装载一个 text 类型的文件。咱们能够先应用此命令将数据装载到一张 TEXT 格局的表中,而后在通过 INSERT OVERWRITE/INTO TABLE ... SELECT
命令将数据装载到其余文件格式的表中。
尖叫提醒:
如果要扭转创立表的默认文件格式,能够应用 hive.default.fileformat=<file_format> 进行配置,改配置能够针对所有表。同时也能够应用 hive.default.fileformat.managed =
<file_format> 进行配置,改配置仅实用于外部表或内部表
TEXT, SEQUENCE 和 AVRO 文件是面向行的文件存储格局,不是最佳的文件格式,因为即使是只查问一列数据,应用这些存储格局的表也须要读取残缺的一行数据。另一方面,面向列的存储格局 (RCFILE, ORC, PARQUET) 能够很好地解决下面的问题。对于每种文件格式的阐明,如下:
- TEXTFILE
创立表时的默认文件格式,数据被存储成文本格式。文本文件能够被宰割和并行处理,也能够应用压缩,比方 GZip、LZO 或者 Snappy。然而大部分的压缩文件不反对宰割和并行处理,会造成一个作业只有一个 mapper 去解决数据,应用压缩的文本文件要确保文件的不要过大,个别靠近两个 HDFS 块的大小。
- SEQUENCEFILE
key/value 对的二进制存储格局,sequence 文件的劣势是比文本格式更好压缩,sequence 文件能够被压缩成块级别的记录,块级别的压缩是一个很好的压缩比例。如果应用块压缩,须要应用上面的配置:set hive.exec.compress.output=true; set io.seqfile.compression.type=BLOCK
- AVRO
二进制格式文件,除此之外,avro 也是一个序列化和反序列化的框架。avro 提供了具体的数据 schema。
- RCFILE
全称是 Record Columnar File,首先将表分为几个行组,对每个行组内的数据进行按列存储,每一列的数据都是离开存储,即先程度划分,再垂直划分。
- ORC
全称是 Optimized Row Columnar,从 hive0.11 版本开始反对,ORC 格局是 RCFILE 格局的一种优化的格局,提供了更大的默认块(256M)
- PARQUET
另外一种列式存储的文件格式,与 ORC 十分相似,与 ORC 相比,Parquet 格局反对的生态更广,比方低版本的 impala 不反对 orc 格局
压缩
压缩技术能够缩小 map 与 reduce 之间的数据传输,从而能够晋升查问性能,对于压缩的配置能够在 hive 的命令行中或者 hive-site.xml 文件中进行配置
SET hive.exec.compress.intermediate=true
开启压缩之后,能够抉择上面的压缩格局:
对于压缩的编码器能够通过 mapred-site.xml, hive-site.xml 进行配置,也能够通过命令行进行配置, 比方:
-- 两头后果压缩
SET hive.intermediate.compression.codec=org.apache.hadoop.io.compress.SnappyCodec
-- 输入后果压缩
SET hive.exec.compress.output=true;
SET mapreduce.output.fileoutputformat.compress.codec=org.apache.hadoop.io.compress.SnappyCodc
存储优化
常常被拜访的数据称之为热数据,能够针对热数据晋升查问的性能。比方通过减少热数据的正本数,能够减少数据本地性命中的可能性,从而晋升查问性能,当然这要与存储容量之间做出衡量。
$ hdfs dfs -setrep -R -w 4 /user/hive/warehouse/employee
留神,大量的小文件或者冗余正本会造成 namenode 节点内存消耗,尤其是大量小于 HDFS 块大小的文件。HDSF 自身提供了应答小文件的解决方案:
- Hadoop Archive/HAR: 将小文件打包成大文件
- SEQUENCEFILE 格局:将小文件压缩成大文件
- CombineFileInputFormat: 在 map 和 reduce 解决之前组合小文件
- HDFS Federation:HDFS 联盟,应用多个 namenode 节点管理文件
对于 Hive 而言,能够应用上面的配置将查问后果的文件进行合并,从而防止产生小文件:
- hive.merge.mapfiles: 在一个仅有 map 的作业中,合并最初的后果文件,默认为 true
- hive.merge.mapredfiles: 合并 mapreduce 作业的后果小文件 默认 false,能够设置 true
- hive.merge.size.per.task: 定义合并文件的大小,默认 256,000,000,即 256MB
- hive.merge.smallfiles.avgsize: T 触发文件合并的文件大小阈值,默认值是 16,000,000
当一个作业的输入后果文件的大小小于 hive.merge.smallfiles.avgsize 设定的阈值,并且 hive.merge.mapfiles 与 hive.merge.mapredfiles 设置为 true,Hive 会额定启动一个 mr 作业将输入小文件合并成大文件。
作业优化
本地模式
当 Hive 解决的数据量较小时,启动分布式去解决数据会有点节约,因为可能启动的工夫比数据处理的工夫还要长,从 Hive0.7 版本之后,Hive 反对将作业动静地转为本地模式,须要应用上面的配置:
SET hive.exec.mode.local.auto=true; -- 默认 false
SET hive.exec.mode.local.auto.inputbytes.max=50000000;
SET hive.exec.mode.local.auto.input.files.max=5; -- 默认 4
一个作业只有满足上面的条件,会启用本地模式
- 输出文件的大小小于
hive.exec.mode.local.auto.inputbytes.max
配置的大小 - map 工作的数量小于
hive.exec.mode.local.auto.input.files.max
配置的大小 - reduce 工作的数量是 1 或者 0
JVM 重用
默认状况下,Hadoop 会为为一个 map 或者 reduce 启动一个 JVM,这样能够并行执行 map 和 reduce。当 map 或者 reduce 是那种仅运行几秒钟的轻量级作业时,JVM 启动过程所消耗的工夫会比作业执行的工夫还要长。Hadoop 能够重用 JVM,通过共享 JVM 以串行而非并行的形式运行 map 或者 reduce。JVM 的重用实用于同一个作业的 map 和 reduce,对于不同作业的 task 不可能共享 JVM。如果要开启 JVM 重用,须要配置一个作业最大 task 数量,默认值为 1,如果设置为 -1,则示意不限度:
SET mapreduce.job.jvm.numtasks=5;
这个性能的毛病是,开启 JVM 重用将始终占用应用到的 task 插槽,以便进行重用,直到工作实现后能力开释。如果某个“不均衡的”job 中有某几个 reduce task 执行的工夫要比其余 Reduce task 耗费的工夫多的多的话,那么保留的插槽就会始终闲暇着却无奈被其余的 job 应用,直到所有的 task 都完结了才会开释。
并行执行
Hive 的查问通常会被转换成一系列的 stage,这些 stage 之间并不是始终相互依赖的,所以能够并行执行这些 stage,能够通过上面的形式进行配置:
SET hive.exec.parallel=true; -- 默认 false
SET hive.exec.parallel.thread.number=16; -- 默认 8
并行执行能够减少集群资源的利用率,如果集群的资源使用率曾经很高了,那么并行执行的成果不会很显著。
Fetch 模式
Fetch 模式是指 Hive 中对某些状况的查问能够不用应用 MapReduce 计算。能够简略地读取表对应的存储目录下的文件,而后输入查问后果到控制台。在开启 fetch 模式之后,在全局查找、字段查找、limit 查找等都启动 mapreduce,通过上面形式进行配置:
hive.fetch.task.conversion=more
JOIN 优化
一般 join
一般 join 又称之为 reduce 端 join,是一种最根本的 join,并且耗时较长。对于大表 join 小表,须要将大表放在右侧,即小表 join 大表。新版的 hive 曾经对小表 JOIN 大表和大表 JOIN 小表进行了优化。小表放在右边和左边曾经没有显著区别。
map 端 join
map 端 join 实用于当一张表很小 (能够存在内存中) 的状况,即能够将小表加载至内存。Hive 从 0.7 开始反对主动转为 map 端 join,具体配置如下:
SET hive.auto.convert.join=true; -- hivev0.11.0 之后默认 true
SET hive.mapjoin.smalltable.filesize=600000000; -- 默认 25m
SET hive.auto.convert.join.noconditionaltask=true; -- 默认 true,所以不须要指定 map join hint
SET hive.auto.convert.join.noconditionaltask.size=10000000; -- 管制加载到内存的表的大小
一旦开启 map 端 join 配置,Hive 会主动查看小表是否大于 hive.mapjoin.smalltable.filesize
配置的大小,如果大于则转为一般的 join,如果小于则转为 map 端 join。
对于 map 端 join 的原理,如下图所示:
首先,Task A(客户端本地执行的 task)负责读取小表 a,并将其转成一个 HashTable 的数据结构,写入到本地文件,之后将其加载至分布式缓存。
而后,Task B 工作会启动 map 工作读取大表 b,在 Map 阶段,依据每条记录与分布式缓存中的 a 表对应的 hashtable 关联,并输入后果
留神:map 端 join 没有 reduce 工作,所以 map 间接输入后果,即有多少个 map 工作就会产生多少个后果文件。
Bucket map join
bucket map join 是一种非凡的 map 端 join,次要区别是其利用在分桶表上。如果要开启分桶的 map 端 join,须要开启一下配置:
SET hive.auto.convert.join=true;
SET hive.optimize.bucketmapjoin=true; -- 默认 false
在一个分桶的 map 端 join 中,所有参加 join 的表必须是分桶表,并且 join 的字段是分桶字段(通过 CLUSTERED BY 指定),另外,对于大表的分桶数量必须是小表分桶数量的倍数。
与一般的 join 相比,分桶 join 仅仅只读取所须要的桶数据,不须要全表扫描。
Sort merge bucket (SMB) join
SMBjoin 利用与分桶表,如果两张参加 join 的表是排序的,并且分桶字段雷同,这样能够应用 sort-merge join,其劣势在于不必把小表齐全加载至内存中,会读取两张分桶表对应的桶,执行一般 join(包含 map 与 reduce)配置如下:
SET hive.input.format=
org.apache.hadoop.hive.ql.io.BucketizedHiveInputFormat;
SET hive.auto.convert.sortmerge.join=true;
SET hive.optimize.bucketmapjoin=true;
SET hive.optimize.bucketmapjoin.sortedmerge=true;
SET hive.auto.convert.sortmerge.join.noconditionaltask=true;
Sort merge bucket map (SMBM) join
SMBM join 是一种非凡的 bucket map join,与 map 端 join 不同的是,不必将小表的所有数据行都加载至内存中。应用 SMBM join,参加 join 的表必须是排序的,有着雷同的分桶字段,并且 join 字段与分桶字段雷同。配置如下:
SET hive.auto.convert.join=true;
SET hive.auto.convert.sortmerge.join=true
SET hive.optimize.bucketmapjoin=true;
SET hive.optimize.bucketmapjoin.sortedmerge=true;
SET hive.auto.convert.sortmerge.join.noconditionaltask=true;
SET hive.auto.convert.sortmerge.join.bigtable.selection.policy=
org.apache.hadoop.hive.ql.optimizer.TableSizeBasedBigTableSelectorForAutoSMJ;
Skew join
当被解决的数据分布极其不平均时,会造成数据歪斜的景象。Hive 能够通过如下的配置优化数据歪斜的状况:
-- 默认 false,如果数据歪斜,能够将其设置为 true
SET hive.optimize.skewjoin=true;
-- 默认为 100000,如果 key 的数量大于配置的值,则超过的数量的 key 对应的数据会被发送到其余的 reduce 工作
SET hive.skewjoin.key=100000;
尖叫提醒:
数据歪斜在 group by 的状况下也会产生,所以能够开启一个配置:set hive.groupby.skewindata=true,优化 group by 呈现的数据歪斜,一旦开启之后,执行作业时会首先额定触发一个 mr 作业,该作业的 map 工作的输入会被随机地调配到 reduce 工作上,从而防止数据歪斜
执行引擎
Hive 反对多种执行引擎,比方 spark、tez。对于执行引擎的抉择,会影响整体的查问性能。应用的配置如下:
SET hive.execution.engine=<engine>; -- <engine> = mr|tez|spark
- mr: 默认的执行引擎,在 Hive2.0 版本版本中被标记过期
- tez: 能够将多个有依赖的作业转换为一个作业,这样只需写一次 HDFS,且两头节点较少,从而大大晋升作业的计算性能。
- spark: 一个通用的大数据计算框架,基于内存计算,速度较快
优化器
与关系型数据库相似,Hive 会在真正执行计算之前,生成和优化逻辑执行打算与物理执行打算。Hive 有两种优化器:Vectorize(向量化优化器)与Cost-Based Optimization (CBO, 老本优化器)。
向量化优化器
向量化优化器会同时解决大批量的数据,而不是一行一行地解决。要应用这种向量化的操作,要求表的文件格式为 ORC,配置如下:
SET hive.vectorized.execution.enabled=true; -- 默认 false
老本优化器
Hive 的 CBO 是基于 apache Calcite 的,Hive 的 CBO 通过查问老本 (有 analyze 收集的统计信息) 会生成有效率的执行打算,最终会缩小执行的工夫和资源的利用,应用 CBO 的配置如下:
SET hive.cbo.enable=true; -- 从 v0.14.0 默认 true
SET hive.compute.query.using.stats=true; -- 默认 false
SET hive.stats.fetch.column.stats=true; -- 默认 false
SET hive.stats.fetch.partition.stats=true; -- 默认 true
总结
本文次要介绍了 Hive 调优的基本思路。总共分为四局部,首先介绍了调优的根本工具应用(explain、analyze); 接着从表设计层面介绍了一些优化策略(分区、分桶、索引);而后介绍了数据存储方面的优化(文件格式、压缩、存储优化);最初从作业层面介绍了优化的技巧(开启本地模式、JVM 重用、并行执行、fetch 模式、Join 优化、执行引擎与优化器)。本文次要为 Hive 性能调优提供一些思路,在理论的操作过程中须要具体问题具体分析。总之一句话,重剑无锋,为作业调配正当的资源基本上能够满足大部分的状况,适宜的就是最好的,没有必要谋求狂拽酷炫的技巧,应该把更多的精力放在业务问题上,因为工具的存在的价值是为了解决业务问题的,切不可轻重倒置。
公众号『大数据技术与数仓』,回复『材料』支付大数据资料包