
# EXPLAIN
#### 功能描述
EXPLAIN命令输出SQL语句的执行计划，通过分析执行计划来定位慢SQL，优化SQL语句。
执行计划将显示SQL语句所引用的表采用的扫描方式，如：简单的顺序扫描、索引扫描等。如果引用了多个表，执行计划还会显示使用的JOIN算法。执行计划的最关键部分是语句的预计执行开销，即计划生成器估算执行该语句将花费多长的时间。
指定ANALYZE选项（EXPLAIN ANALYZE），不仅显示执行计划，还会实际执行查询，并提供每个步骤的实际执行时间。这有助于验证执行计划的准确性，并评估实际性能。
详细的SQL调优介绍及指导请参考[SQL调优](https://support.huaweicloud.com/devg-dws/dws_04_0430.html)。
#### 语法格式
- 显示SQL语句的执行计划，支持多种选项，对选项顺序无要求：
  ```
  EXPLAIN [ (  option  [, ...] )  ] statement;
  ```
  其中选项option子句的语法为：
  ```
  ANALYZE [ boolean ] |
      ANALYSE [ boolean ] |
      VERBOSE [ boolean ] |
      COSTS [ boolean ] |
      CPU [ boolean ] |
      DETAIL [ boolean ] |
      NODES [ boolean ] |
      NUM_NODES [ boolean ] |
      BUFFERS [ boolean ] |
      TIMING [ boolean ] |
      PLAN [ boolean ] |
      FORMAT { TEXT | XML | JSON | YAML } |
      BLOCKNAME [boolean] |
      OUTLINE [boolean]  |
      WARMUP |
      WARMUP HOT
  ```
  
- 显示SQL语句的执行计划，且要按顺序给出选项：
  ```
  EXPLAIN  { [  { ANALYZE  | ANALYSE  }  ] [ VERBOSE  ]  | PERFORMANCE  } statement;
  ```
  
- 显示复现SQL语句的执行计划所需的信息，通常用于定位问题。STATS选项必须单独使用：
  ```
  EXPLAIN ( STATS [ boolean ] ) statement;
  ```
  
 
- 显示DDL语句执行步骤的详细耗时信息。（该语法仅9.1.0及以上集群版本支持）
  ```
  EXPLAIN PERFORMANCE statement;
  ```
  支持的DDL语句有CREATE、CREATE INDEX、DROP、VACUUM FULL、ANALYZE及COPY。
  
- 执行预查询，并将预查询的数据缓存到本地磁盘，提升实际查询时的查询速度。（该语法仅9.1.0.200及以上集群版本支持）
  ```
  EXPLAIN WARMUP statement;
  ```
  ```
  EXPLAIN WARMUP HOT statement;
  ```
  
#### 参数说明
表1EXPLAIN参数说明 
| 参数                                 | 描述                                                                                                                                                                                                                                                                                                                                   | 取值范围                                                                                                                                                                                                                                                                                                                                              |
|:---|:---|:---|
| statement                          | 需要分析的SQL语句。                                                                                                                                                                                                                                                                                                                          | -                                                                                                                                                                                                                                                                                                                                                 |
| ANALYZE boolean \| ANALYSE boolean | 指定ANALYZE选项时，会实际执行SQL，根据实际的运行结果显示统计数据，包括每个计划节点内时间总开销（毫秒为单位）和实际返回的总行数。 如果使用EXPLAIN分析INSERT，UPDATE，DELETE，CREATE TABLE AS或EXECUTE语句，但不改动数据（执行这些语句会影响数据），可以放在一个事务中，分析完成后可以直接回滚： ``` START TRANSACTION; EXPLAIN ANALYZE ...; ROLLBACK; ``` | - TRUE：显示实际运行时间和其他统计数据。  - FALSE：不显示。   缺省值：TRUE                                                     |
| VERBOSE boolean                    | 显示查询计划的附加信息。 附加信息包括查询计划中每个节点输出的列（Output），表的SCHEMA信息，函数的模式信息，表达式中列所属表的别名，被触发的触发器名称等。                                                                                                                                                                                                   | - TRUE：显示附加信息。  - FALSE：不显示。   缺省值：TRUE                                                          |
| COSTS boolean                      | 显示每个计划节点的预估总成本，以及预估行数和每行宽度。                                                                                                                                                                                                                                                                                                          | - TRUE：显示估计总成本和宽度。  - FALSE：不显示。   缺省值：TRUE                                                           |
| CPU boolean                        | 显示CPU的使用情况。                                                                                                                                                                                                                                                                                                                          | - TRUE：显示CPU的使用情况。  - FALSE：不显示。   缺省值：TRUE                                                     |
| DETAIL boolean                     | 显示DN上的信息。 说明： 8.2.1及以上集群版本支持explain打开Detail开关时，执行计划中会显示倾斜值比对耗时。                                                                                                                                                                         | - TRUE：打印DN的信息。  - FALSE：不打印。   缺省值：TRUE                                                      |
| NODES boolean                      | 打印query执行的节点信息。                                                                                                                                                                                                                                                                                                                      | - TRUE：打印执行的节点的信息。  - FALSE：不打印。   缺省值：TRUE                                                    |
| NUM_NODES boolean                  | 打印执行中的节点的个数信息。                                                                                                                                                                                                                                                                                                                       | - TRUE：打印DN个数的信息。  - FALSE：不打印。   缺省值：TRUE                                                           |
| BUFFERS boolean                    | 显示缓冲区的使用信息。 缓冲区信息包括共享块（常规表或者索引块）、本地块（临时表或者索引块）和临时块（排序或者哈希等涉及到的短期存在的数据块）的命中块数，读取块数，更新块数等。                                                                                                                                                                                               | - TRUE：显示缓冲区的使用情况。  - FALSE：不显示。   缺省值：FALSE                                                       |
| TIMING boolean                     | 显示每个计划节点的实际启动时间和总的执行时间。                                                                                                                                                                                                                                                                                                              | - TRUE：显示启动时间和花费在输出节点上的时间信息。  - FALSE：不显示。   缺省值：TRUE                                                     |
| PLAN boolean                       | 是否将执行计划存储在plan_table中。当该选项开启时，会将执行计划存储在PLAN_TABLE中，不打印到当前屏幕，因此该选项为on时，不能与其他选项同时使用。                                                                                                                                                                                                                                                   | - ON：将执行计划存储在plan_table中，不打印到当前屏幕。执行成功返回EXPLAIN SUCCESS。  - OFF：不存储执行计划，将执行计划打印到当前屏幕。   缺省值：ON |
| FORMAT                             | 指定输出格式。 各个格式输出的内容都是相同的，其中XML \| JSON \| YAML更有利于您通过程序解析SQL语句的查询计划。                                                                                                                                                                                                                   | 支持四种格式：TEXT，XML，JSON和YAML。 缺省值：TEXT                                                                                                                                                                                                                                                                  |
| BLOCKNAME boolean                  | 显示算子的blockname信息。 仅在explain_perf_mode取值为pretty时，打印blockname信息。                                                                                                                                                                                                                         | - TRUE：显示blockname信息。  - FALSE：不显示blockname信息。   缺省值：TRUE                                            |
| OUTLINE boolean                    | 显示从计划中提取的outline信息。 仅在explain_perf_mode取值为pretty时，打印outline信息。                                                                                                                                                                                                                      | - TRUE：显示outline信息。  - FALSE：不显示outline信息。   缺省值：TRUE                                             |
| PERFORMANCE                        | 使用此选项时，即打印执行中的所有相关信息。                                                                                                                                                                                                                                                                                                                | -                                                                                                                                                                                                                                                                                                                                                 |
| STATS boolean                      | 打印复现SQL语句的执行计划所需的信息，包括对象定义、统计信息、配置参数等，通常用于定位问题。                                                                                                                                                                                                                                                                                      | - TRUE：显示复现SQL语句的执行计划所需的信息。  - FALSE：不显示。   缺省值：TRUE                                               |
| WARMUP                             | warmup将查询数据按照A1in \> A1out \> Am的顺序进行。该参数仅9.1.0.200及以上集群版本支持。                                                                                                                                                                                                                                                                        | -                                                                                                                                                                                                                                                                                                                                                 |
| WARMUP HOT                         | warmup hot将查询的数据直接加入am列。该参数仅9.1.0.200及以上集群版本支持。                                                                                                                                                                                                                                                                                      | -                                                                                                                                                                                                                                                                                                                                                 |
   
#### 示例
创建一个表tpcds.customer_address_p1。
```
CREATE TABLE tpcds.customer_address_p1 AS TABLE tpcds.customer_address;
```
修改explain_perf_mode为normal。
```
SET explain_perf_mode=normal;
```
显示表简单查询的执行计划。
```
EXPLAIN SELECT * FROM tpcds.customer_address_p1;
       QUERY PLAN
----------------------------------------------------------------------------
 Data Node Scan on "__REMOTE_FQS_QUERY__"  (cost=0.00..0.00 rows=0 width=0)
   Node/s: All datanodes
(2 rows)
```
以JSON格式输出的执行计划（explain_perf_mode为normal时）。
```
EXPLAIN(FORMAT JSON) SELECT * FROM tpcds.customer_address_p1;
                    QUERY PLAN
---------------------------------------------------
 [                                                +
   {                                              +
     "Plan": {                                    +
       "Node Type": "Data Node Scan",             +
       "RemoteQuery name": "__REMOTE_FQS_QUERY__",+
       "Alias": "__REMOTE_FQS_QUERY__",           +
       "Startup Cost": 0.00,                      +
       "Total Cost": 0.00,                        +
       "Plan Rows": 0,                            +
       "Plan Width": 0,                           +
       "Nodes": "All datanodes"                   +
     }                                            +
   }                                              +
 ]
(1 row)
```
如果有一个索引，当使用一个带索引WHERE条件的查询，可能会显示一个不同的计划。
```
EXPLAIN SELECT * FROM tpcds.customer_address_p1 WHERE ca_address_sk=10000;
                                  QUERY PLAN
------------------------------------------------------------------------------
 Data Node Scan on "__REMOTE_LIGHT_QUERY__"  (cost=0.00..0.00 rows=0 width=0)
   Node/s: datanode2
(2 rows)
```
以YAML格式输出的执行计划（explain_perf_mode为normal时）。
```
EXPLAIN(FORMAT YAML) SELECT * FROM tpcds.customer_address_p1 WHERE ca_address_sk=10000;
                   QUERY PLAN
------------------------------------------------
 - Plan:                                       +
     Node Type: "Data Node Scan"               +
     RemoteQuery name: "__REMOTE_LIGHT_QUERY__"+
     Alias: "__REMOTE_LIGHT_QUERY__"           +
     Startup Cost: 0.00                        +
     Total Cost: 0.00                          +
     Plan Rows: 0                              +
     Plan Width: 0                             +
     Nodes: "datanode2"
(1 row)
```
禁止开销估计的执行计划。
```
EXPLAIN(COSTS FALSE)SELECT * FROM tpcds.customer_address_p1 WHERE ca_address_sk=10000;
                 QUERY PLAN
--------------------------------------------
 Data Node Scan on "__REMOTE_LIGHT_QUERY__"
   Node/s: datanode2
(2 rows)
```
带有聚集函数查询的执行计划。
```
EXPLAIN SELECT SUM(ca_address_sk) FROM tpcds.customer_address_p1 WHERE ca_address_sk<10000;
                                      QUERY PLAN                                       
---------------------------------------------------------------------------------------
 Aggregate  (cost=18.19..14.32 rows=1 width=4)
   ->  Streaming (type: GATHER)  (cost=18.19..14.32 rows=3 width=4)
         Node/s: All datanodes
         ->  Aggregate  (cost=14.19..14.20 rows=3 width=4)
               ->  Seq Scan on customer_address_p1  (cost=0.00..14.18 rows=10 width=4)
                     Filter: (ca_address_sk < 10000)
(6 rows)
```
删除表tpcds.customer_address_p1。
```
DROP TABLE tpcds.customer_address_p1;
```
对ANALYZE语句执行EXPLAIN PERFORMANCE。
```
EXPLAIN PERFORMANCE ANALYZE t2_dist_row;
                            QUERY EXEC INFO                            
-----------------------------------------------------------------------
 lock FirstCN: 
        coordinator1: actual time=0.240 loops=1
 estimate rows: actual time=[datanode3 0.000, datanode1 0.001]
        coordinator1: actual time=0.000 loops=1
        datanode1: actual time=0.001 loops=1
        datanode2: actual time=0.000 loops=1
        datanode3: actual time=0.000 loops=1
 sample rows: actual time=[datanode1 5.109, coordinator1 119.838]
        coordinator1: actual time=119.838 loops=1
        datanode1: actual time=5.109 loops=1
        datanode2: actual time=5.621 loops=1
        datanode3: actual time=5.342 loops=1
 fetch global stats: 
        coordinator1: actual time=8.501 loops=1
 calc stats: actual time=[datanode3 80.794, datanode2 109.155]
        coordinator1: actual time=97.452 loops=1
        datanode1: actual time=94.375 loops=1
        datanode2: actual time=109.155 loops=1
        datanode3: actual time=80.794 loops=1
 calc column stats: actual time=[datanode2 0.938, datanode3 9.811]
        coordinator1: actual time=5.162 loops=2
        datanode1: actual time=1.453 loops=2
        datanode2: actual time=0.938 loops=2
        datanode3: actual time=9.811 loops=2
 calc index stats: actual time=[datanode3 12.392, coordinator1 36.113]
        coordinator1: actual time=36.113 loops=1
        datanode1: actual time=15.933 loops=1
        datanode2: actual time=13.419 loops=1
        datanode3: actual time=12.392 loops=1
 calc expr stats: actual time=[datanode3 41.665, datanode2 78.442]
        coordinator1: actual time=55.608 loops=1
        datanode1: actual time=63.179 loops=1
        datanode2: actual time=78.442 loops=1
        datanode3: actual time=41.665 loops=1
 sync stats: 
        coordinator1: actual time=7.906 loops=1
 General Tracks
 CN build CN connection: 
        coordinator1: actual time=0.002 loops=1
 CN build DN connection: 
        coordinator1: actual time=0.070 loops=1
 -> execute ddl on other CN: 
        coordinator1: actual time=0.001 loops=1
 -> execute ddl on other DN: 
        coordinator1: actual time=0.000 loops=1
 Query Id: 72902018968225366
 Total runtime: 242.211 ms
(48 rows)
```
显示计划的blockname信息。
```
EXPLAIN (BLOCKNAME ON) SELECT SUM(ca_address_sk) FROM tpcds.customer_address_p1 WHERE ca_address_sk<10000;
                                         QUERY PLAN
---------------------------------------------------------------------------------------------
  id |                  operation                   | E-rows | E-memory | E-width | E-costs
 ----+----------------------------------------------+--------+----------+---------+---------
   1 | ->  Aggregate                                |      1 |          |      12 | 16.14
   2 |    ->  Streaming (type: GATHER)              |      2 |          |      12 | 16.14
   3 |       ->  Aggregate                          |      2 | 1MB      |      12 | 10.14
   4 |          ->  Seq Scan on customer_address_p1 |      7 | 1MB      |       4 | 10.12
 Predicate Information (identified by plan id)
 ---------------------------------------------
   4 --Seq Scan on customer_address_p1
         Filter: (ca_address_sk < 10000)
 Query Block Name / Object Alias (identified by plan id)
 -------------------------------------------------------
   1 - sel$1
   4 - sel$1 / customer_address_p1@"sel$1"
   ====== Query Summary =====
 -------------------------------
 System available mem: 4710400KB
 Query Max mem: 4710400KB
 Query estimated mem: 2048KB
(22 rows)
```
显示计划的outline信息。
```
EXPLAIN (OUTLINE ON) SELECT SUM(ca_address_sk) FROM tpcds.customer_address_p1 WHERE ca_address_sk<10000;
                                         QUERY PLAN
---------------------------------------------------------------------------------------------
  id |                  operation                   | E-rows | E-memory | E-width | E-costs
 ----+----------------------------------------------+--------+----------+---------+---------
   1 | ->  Aggregate                                |      1 |          |      12 | 16.14
   2 |    ->  Streaming (type: GATHER)              |      2 |          |      12 | 16.14
   3 |       ->  Aggregate                          |      2 | 1MB      |      12 | 10.14
   4 |          ->  Seq Scan on customer_address_p1 |      7 | 1MB      |       4 | 10.12
 Predicate Information (identified by plan id)
 ---------------------------------------------
   4 --Seq Scan on customer_address_p1
         Filter: (ca_address_sk < 10000)
                         Outline Data
 ------------------------------------------------------------
   /*+
       begin_outline_data
        TableScan(@"sel$1" tpcds.customer_address_p1@"sel$1")
       end_outline_data
   */
   ====== Query Summary =====
 -------------------------------
 System available mem: 4710400KB
 Query Max mem: 4710400KB
 Query estimated mem: 2048KB
(25 rows)
```
#### 相关链接
[ANALYZE \| ANALYSE](https://support.huaweicloud.com/sqlreference-dws/dws_06_0245.html)
