SQL 执行计划的展示是了解 SQL 执行逻辑和性能调优的最重要的手段。用户可以通过 explain 命令查看优化器针对给定SQL 生成的逻辑执行计划。在执行 explain 命令时,系统会为给定的 SQL 生成最终的逻辑执行计划并展示给用户,但并不会生成相应的物理执行计划(可执行的代码),也不会真正执行该计划或者将该计划放入计划缓存。

Explain 命令格式

Explain 命令格式如下例所示,展示的格式包括 BASIC、EXTENDED、PARTITIONS 等。

  1. EXPLAIN [BASIC | EXTENDED | PARTITIONS | FORMAT = format_name] explainable_stmt
  2. format_name: { TRADITIONAL | JSON }
  3. explainable_stmt: { SELECT statement
  4. | DELETE statement
  5. | INSERT statement
  6. | REPLACE statement
  7. | UPDATE statement }

计划形状与算子信息

Explain 输出的第一部分是执行计划的树形结构展示。其中每一个操作在树中的层次通过其在 OPERATOR 中的缩进予以展示。如下例所示:

  1. |==========================================
  2. |ID|OPERATOR |NAME|EST. ROWS|COST|
  3. ------------------------------------------
  4. |0 |SORT | |1 |2763|
  5. |1 | MERGE INNER JOIN| |1 |2735|
  6. |2 | SORT | |1000 |1686|
  7. |3 | TABLE SCAN |t2 |1000 |1180|
  8. |4 | TABLE SCAN |t1 |1 |815 |
  9. ==========================================

其对应的树状执行计划如下图所示:

执行计划展示 (EXPLAIN) - 图1

执行计划中的各项的含义如下:

列名含义
ID执行树按照前序遍历的方式得到的编号(从0开始)
OPERATOR操作算子的名称
NAME对应表操作的表名(索引名)
EST. ROWS估算的该操作算子的输出行数
COST该操作算子的执行代价(微秒)

在表操作中,NAME 字段会显示该操作涉及的表的名称(别名),如果是使用索引访问,还会在名称后的括号中展示该索引的名称, 例如 t1(t1_c2) 表示使用了 t1_c2 这个索引。另外,如果扫描的顺序是逆序,还会在后面使用 reserve 关键字标识,例如 t1(t1_c2,Reverse)。

一些常见的算子类型归纳如下表:

类型算子
表访问table scan, table get
连接NESTED-LOOP, BLK-NESTED-LOOP,Merge、hash
排序sort,top-n sort
聚合merge group-by,hash group-by, window function
分布式exchange in/out remote/distribute
集合union, except, intersect,minus
其他limit, material, subplan, expression, count

操作算子详细输出

Explain 输出的第二部分是各操作算子的详细信息,包括输出表达式、过滤条件、分区信息以及各算子的独有信息,包括排序键、连接键、下压条件等。

  1. Outputs & filters:
  2. -------------------------------------
  3. 0 - output([t1.c1], [t1.c2], [t2.c1], [t2.c2]), filter(nil), sort_keys([t1.c1, ASC], [t1.c2, ASC]), prefix_pos(1)
  4. 1 - output([t1.c1], [t1.c2], [t2.c1], [t2.c2]), filter(nil),
  5. equal_conds([t1.c1 = t2.c2]), other_conds(nil)
  6. 2 - output([t2.c1], [t2.c2]), filter(nil), sort_keys([t2.c2, ASC])
  7. 3 - output([t2.c2], [t2.c1]), filter(nil),
  8. access([t2.c2], [t2.c1]), partitions(p0)
  9. 4 - output([t1.c1], [t1.c2]), filter(nil),
  10. access([t1.c1], [t1.c2]), partitions(p0)

一些常用的信息含义如下表:

信息名称含义
output该算子的输出表达式列表
filter该算子执行的过滤条件
access表访问中存储层的投影列名
partitions分区裁剪的信息
sort_keys排序操作的排序键
prefix_pos局部有序的偏移位置
equal_conds连接操作中执行的等值连接条件
other_conds连接操作中执行的非等值连接条件