Hive提供了explain命令来展示一个查询的执行计划,这个执行计划对于我们了解底层原理,Hive 调优,排查数据倾斜等很有帮助。
使用语法如下:
explain query;
在 hive cli 中输入以下命令(hive 2.3.7):
explain select sum(id) from test1;
得到结果:
STAGE DEPENDENCIES:Stage-1 is a root stageStage-0 depends on stages: Stage-1STAGE PLANS:Stage: Stage-1Map ReduceMap Operator Tree:TableScanalias: test1Statistics: Num rows: 6 Data size: 75 Basic stats: COMPLETE Column stats: NONESelect Operatorexpressions: id (type: int)outputColumnNames: idStatistics: Num rows: 6 Data size: 75 Basic stats: COMPLETE Column stats: NONEGroup By Operatoraggregations: sum(id)mode: hashoutputColumnNames: _col0Statistics: Num rows: 1 Data size: 8 Basic stats: COMPLETE Column stats: NONEReduce Output Operatorsort order:Statistics: Num rows: 1 Data size: 8 Basic stats: COMPLETE Column stats: NONEvalue expressions: _col0 (type: bigint)Reduce Operator Tree:Group By Operatoraggregations: sum(VALUE._col0)mode: mergepartialoutputColumnNames: _col0Statistics: Num rows: 1 Data size: 8 Basic stats: COMPLETE Column stats: NONEFile Output Operatorcompressed: falseStatistics: Num rows: 1 Data size: 8 Basic stats: COMPLETE Column stats: NONEtable:input format: org.apache.hadoop.mapred.SequenceFileInputFormatoutput format: org.apache.hadoop.hive.ql.io.HiveSequenceFileOutputFormatserde: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDeStage: Stage-0Fetch Operatorlimit: -1Processor Tree:ListSink
我们将上述结果拆分看,先从最外层开始,包含两个大的部分:
-
stage dependencies:各个stage之间的依赖性
-
stage plan:各个stage的执行计划
先看第一部分 stage dependencies ,包含两个 stage,Stage-1 是根stage,说明这是开始的stage,Stage-0 依赖 Stage-1,Stage-1执行完成后执行Stage-0。
再看第二部分 stage plan,里面有一个 Map Reduce,一个MR的执行计划分为两个部分:
-
Map Operator Tree:MAP端的执行计划树
-
Reduce Operator Tree:Reduce端的执行计划树
这两个执行计划树里面包含这条sql语句的 operator:
-
TableScan:表扫描操作,map端第一个操作肯定是加载表,所以就是表扫描操作,常见的属性:
-
alias:表名称
-
Statistics:表统计信息,包含表中数据条数,数据大小等
-
-
Select Operator:选取操作,常见的属性 :
-
expressions:需要的字段名称及字段类型
-
outputColumnNames:输出的列名称
-
Statistics:表统计信息,包含表中数据条数,数据大小等
-
-
Group By Operator:分组聚合操作,常见的属性:
-
aggregations:显示聚合函数信息
-
mode:聚合模式,值有 hash:随机聚合,就是hash partition;partial:局部聚合;final:最终聚合
-
keys:分组的字段,如果没有分组,则没有此字段
-
outputColumnNames:聚合之后输出列名
-
Statistics:表统计信息,包含分组聚合之后的数据条数,数据大小等
-
-
Reduce Output Operator:输出到reduce操作,常见属性:
-
sort order:值为空 不排序;值为 + 正序排序,值为 - 倒序排序;值为 +- 排序的列为两列,第一列为正序,第二列为倒序
-
-
Filter Operator:过滤操作,常见的属性:
-
predicate:过滤条件,如sql语句中的where id>=1,则此处显示(id >= 1)
-
-
Map Join Operator:join 操作,常见的属性:
-
condition map:join方式 ,如Inner Join 0 to 1 Left Outer Join0 to 2
-
keys: join 的条件字段
-
outputColumnNames:join 完成之后输出的字段
-
Statistics:join 完成之后生成的数据条数,大小等
-
-
File Output Operator:文件输出操作,常见的属性
-
compressed:是否压缩
-
table:表的信息,包含输入输出文件格式化方式,序列化方式等
-
-
Fetch Operator 客户端获取数据操作,常见的属性:
-
limit,值为 -1 表示不限制条数,其他值为限制的条数。
-
定位产生数据倾斜的代码段
数据倾斜大多数都是大 key 问题导致的。
如何判断是大 key 导致的问题,可以通过下面方法:
1. 通过时间判断
如果某个 reduce 的时间比其他 reduce 时间长的多,如下图,大部分 task 在 1 分钟之内完成,只有 r_000000 这个 task 执行 20 多分钟了还没完成。
定位 SQL 代码
确定任务卡住的 stage
- 通过 jobname 确定 stage:
一般 Hive 默认的 jobname 名称会带上 stage 阶段,如下通过 jobname 看到任务卡住的为 Stage-4:
- 如果 jobname 是自定义的,那可能没法通过 jobname 判断 stage。需要借助于任务日志:
找到执行特别慢的那个 task,然后 Ctrl+F 搜索 “CommonJoinOperator: JOIN struct” 。Hive 在 join 的时候,会把 join 的 key 打印到日志中。如下:
上图中的关键信息是:struct<_col0:string, _col1:string, _col3:string>
这时候,需要参考该 SQL 的执行计划。通过参考执行计划,可以断定该阶段为 Stage-4 阶段:
2. 确定 SQL 执行代码
确定了执行阶段,即 Stage-4 阶段。通过执行计划,则可以判断出是执行哪段代码时出现了倾斜。还是从此图,这个 Stage-4 阶段中进行连接操作的表别名是 d:
就可以推测出是在执行下面红框中代码时出现了数据倾斜,因为这行的表的别名是 d:
以上仅列举了4个我们生产中既熟悉又有点迷糊的例子,explain 还有很多其他的用途,如查看stage的依赖情况、hive 调优等,小伙伴们可以自行尝试。