利用impala query profile解决性能问题(一)Impala plan and profile

参考资料

由于经常有Impala SQL将一台或多台 Impalad 所在的机器的内存消耗殆尽,而通常的解决方案是直接取消该SQL查询。我一直以来总想优雅地去处理这些SQL,比如挂个钩子给客户端返回一些执行计划信息,告知如何优化 SQL,或者直接给他调整优化重新提交SQL等等。
那如何从一堆profile信息中提取关键信息是我首先要解决的。
所以,我花了一些时间仔细地研究了Impala 的 执行计划(plan)及概要(profile)。重点参考了油管上这个专题内容:How to use Impala’s query plan and profile to fix Performance
英文比较好的小伙伴完全可以跳过我的文章直接进行学习。

一、Impala SQL执行流程及架构

首先先看

1. SQL执行流程。

在这里插入图片描述
Impalad 分为Java前端与C++处理后端,接受客户端连接的Impalad即作为这次查询的Coordinator,Coordinator通过JNI调用Java前端对用户的查询SQL进行分析生成执行计划树。
Java前端产生的执行计划树以 Thrift 数据格式返回给 Impala C++后端(Coordinator),由 Coordinator 根据执行计划,通过调度器对生成的执行计划树分配给相应的后端执行器 Impalad 执行,并把结果通过网络流式的传送回给Coordinator,由Coordinator 返回给客户端。

2. Impala 的逻辑结构:

这边是以 CDH6.3.2 为例,CDP 权限验证使用的是Ranger。
在这里插入图片描述
总体可分为元数据(控制层)、执行层、存储层。
StateStore:检查集群中所有 Impalad 的运行状况,并不断将其结果转发给每个 Impalad,同时持续将元数据广播给协调器。
Catalog:缓存元数据,包含 HDFS 元数据和数据库、表字段等元数据,以及与安全相关的信息、授权信息等。一旦 Catalog 加载了这些元数据,就会将他们缓存,并发送给 StateStore,然后分发给 Impalad。
Impalad:接受客户端查询,解析查询请求,编译生成并行任务,然后分发任务到其他 Impalad 并行执行,并返回结果。
每个Impalad都可以既做 Coordinator 又做 Executor,他们分别是上面第一张图中说的 Impalad 的前端和后端。(但其实一般会配置专用 Coordinator 角色)

二、什么是 Impala查询计划和概要

1. 查询计划(Plan)

Impala 的执行计划是Impala根据客户端提交的 SQL 生成的一系列操作节点图,不同的操作对应不同的 PlanNode, 如:‌ScanNode、SortNode、 AggregationNode, HashJoinNode、‌LimitNode、‌UnionNode、ExchangeNode 等等。Impala生成执行计划的主要目的如下:

  • 通过分区裁剪、谓词下推、运行时过滤器等方法,尽可能减少不必要的工作
  • 使用 DN 块元数据最大化扫描位置。
  • 最小化数据移动(优化连接顺序,选择更好的连接策略)
  • 将任务并行化,在多个节点上运行,以缩短执行时间。

2. 查询概要(Profile)

‌Impala Profile‌是Impala在执行SQL查询时生成的一种详细报告,它提供了查询执行过程中的各种参数和统计信息,帮助用户理解查询的执行过程、识别性能瓶颈并进行优化。

三、在哪看执行计划和概要

1. CM查询历史页:

在这里插入图片描述

点击查询详细信息

在这里插入图片描述

2. Impala WebUI:

只能在 Impala Coordinator上可以查看:

在这里插入图片描述

这边有 plan 拓扑图,颜色越暖,表示消耗的资源越多。

在这里插入图片描述

3. Impala-shell

通过 explain命令可以查询 plan,执行结束后通过 profile查询详细的执行概要。
explain有三种级别,1-3,其中 1 表示最低级别,输出的执行计划比较简单,3表示最高级别,输出的执行计划最详细。

set explain_level=1;

[node2:21000] testdb> set explain_level=1;
EXPLAIN_LEVEL set to 1
[node2:21000] testdb> explain select c.c_name,sum(o.o_totalprice*l.l_quantity)
from customer c
join orders o on c.c_custkey=o.o_custkey
join lineitem l on l.l_orderkey = o.o_orderkey
group by c.c_name;
Query: explain select c.c_name,sum(o.o_totalprice*l.l_quantity)
from customer c
join orders o on c.c_custkey=o.o_custkey
join lineitem l on l.l_orderkey = o.o_orderkey
group by c.c_name
+------------------------------------------------------------------------------------+
| Explain String                                                                     |
+------------------------------------------------------------------------------------+
| Max Per-Host Resource Reservation: Memory=139.02MB Threads=8                       |
| Per-Host Resource Estimates: Memory=4.43GB                                         |
| WARNING: The following tables are missing relevant table and/or column statistics. |
| testdb.customer, testdb.lineitem, testdb.orders                                    |
|                                                                                    |
| PLAN-ROOT SINK                                                                     |
| |                                                                                  |
| 10:EXCHANGE [UNPARTITIONED]                                                        |
| |                                                                                  |
| 09:AGGREGATE [FINALIZE]                                                            |
| |  output: sum:merge(o.o_totalprice * l.l_quantity)                                |
| |  group by: c.c_name                                                              |
| |  row-size=27B cardinality=unavailable                                            |
| |                                                                                  |
| 08:EXCHANGE [HASH(c.c_name)]                                                       |
| |                                                                                  |
| 05:AGGREGATE [STREAMING]                                                           |
| |  output: sum(o.o_totalprice * l.l_quantity)                                      |
| |  group by: c.c_name                                                              |
| |  row-size=27B cardinality=unavailable                                            |
| |                                                                                  |
| 04:HASH JOIN [INNER JOIN, BROADCAST]                                               |
| |  hash predicates: o.o_orderkey = l.l_orderkey                                    |
| |  runtime filters: RF000 <- l.l_orderkey                                          |
| |  row-size=67B cardinality=unavailable                                            |
| |                                                                                  |
| |--07:EXCHANGE [BROADCAST]                                                         |
| |  |                                                                               |
| |  02:SCAN HDFS [testdb.lineitem l]                                                |
| |     partitions=1/1 files=8 size=48B                                              |
| |     row-size=15B cardinality=unavailable                                         |
| |                                                                                  |
| 03:HASH JOIN [INNER JOIN, BROADCAST]                                               |
| |  hash predicates: c.c_custkey = o.o_custkey                                      |
| |  runtime filters: RF002 <- o.o_custkey                                           |
| |  row-size=52B cardinality=unavailable                                            |
| |                                                                                  |
| |--06:EXCHANGE [BROADCAST]                                                         |
| |  |                                                                               |
| |  01:SCAN HDFS [testdb.orders o]                                                  |
| |     partitions=1/1 files=8 size=263B                                             |
| |     runtime filters: RF000 -> o.o_orderkey                                       |
| |     row-size=30B cardinality=unavailable                                         |
| |                                                                                  |
| 00:SCAN HDFS [testdb.customer c]                                                   |
|    partitions=1/1 files=5 size=99B                                                 |
|    runtime filters: RF002 -> c.c_custkey                                           |
|    row-size=22B cardinality=unavailable                                            |
+------------------------------------------------------------------------------------+

set explain_level=3;

[node2:21000] testdb> set explain_level=3;
EXPLAIN_LEVEL set to 3
[node2:21000] testdb> explain select c.c_name,sum(o.o_totalprice*l.l_quantity)
from customer c
join orders o on c.c_custkey=o.o_custkey
join lineitem l on l.l_orderkey = o.o_orderkey
group by c.c_name;
Query: explain select c.c_name,sum(o.o_totalprice*l.l_
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值