EXPLAIN 输出格式
输出结构
语法结构执行结果是为 statement 选择的计划的文本描述,可以选择使用执行统计信息进行注释。
以下以 TPCH 中数据集的查询分析为例,演示输出结构:
explain SELECT * FROM customer WHERE c_nationkey = (SELECT n_nationkey FROM nation
WHERE customer.c_nationkey  = nation.n_nationkey  AND nation.n_nationkey > 5);
mysql> explain SELECT * FROM customer WHERE c_nationkey = (SELECT n_nationkey FROM nation
    -> WHERE customer.c_nationkey  = nation.n_nationkey  AND nation.n_nationkey > 5);
+----------------------------------------------------------------------+
| QUERY PLAN                                                           |
+----------------------------------------------------------------------+
| Project                                                              |
|   ->  Filter                                                         |
|         Filter Cond: (customer.c_nationkey = nation.n_nationkey)     |
|         ->  Join                                                     |
|               Join Type: SINGLE   hashOnPK                           |
|               Join Cond: (customer.c_nationkey = nation.n_nationkey) |
|               ->  Table Scan on tpch.customer                        |
|               ->  Table Scan on tpch.nation                          |
|                     Filter Cond: (nation.n_nationkey > 5)            |
|                     Block Filter Cond: (nation.n_nationkey > 5)      |
+----------------------------------------------------------------------+
10 rows in set (0.01 sec)
EXPLAIN 输出一个名称为 QUERY PLAN 树形结构,每个叶子节点都包含节点类型、受影响的对象。我们现在只使用节点类型信息来简化展示上面的示例。QUERY PLAN 树形结构可以可视化 SQL 查询的整个过程,显示它所经过的操作节点。
Project
└── Filter
    └── Join
        └── Table Scan
        └── Table Scan
节点类型
MatrixOne 支持以下节点类型。
| 节点名称 | 含义 | 
|---|---|
| Values Scan | 处理值的扫描 | 
| Table Scan | 从表中扫描数据 | 
| External Scan | 处理外部的数据扫描 | 
| Source Scan | 处理 source 表的数据扫描 | 
| Project | 对数据进行投影运算 | 
| Sink | 分发同一份数据给一个 / 多个对象 | 
| Sink Scan | 读取其他对象分发过来的数据 | 
| Recursive Scan | 循环 CTE 语法中,处理每次循环结束时的数据,判断是否开启下一轮循环 | 
| CTE Scan | 循环 CTE 语法中,读每次循环开始时的数据 | 
| Aggregate | 对数据进行聚合 | 
| Filter | 对数据进行过滤 | 
| Join | 对数据进行连接运算 | 
| Sample | SAMPLE 采样函数,对数据进行抽样 | 
| Sort | 对数据进行排序 | 
| Partition | 范围窗口中对数据进行排序,并按值切分 | 
| Union | 对两个或多个查询的结果集组合 | 
| Union All | 对两个或多个查询的结果集组合,包括重复行 | 
| Window | 对数据进行范围窗口计算 | 
| Time Window | 对数据进行时间窗口计算 | 
| Fill | 处理时间窗口中的 NULL 值 | 
| Insert | 对数据进行插入 | 
| Delete | 对数据进行删除 | 
| Intersect | 对两个或多个查询的都存在的行组合 | 
| Intersect All | 对两个或多个查询的都存在的行组合,包括重复行 | 
| Minus | 比较两个查询的结果,返回存在于第一个查询而在第二个查询中不存在的行 | 
| Table Function | 通过表函数读取数据 | 
| PreInsert | 整理要写入的数据 | 
| PreInsert UniqueKey | 整理要写入到唯一键隐藏表的数据 | 
| PreInsert SecondaryKey | 整理要写入到次级索引隐藏表的数据 | 
| PreDelete | 整理分区表所需要删除的数据。 | 
| On Duplicate Key | 对重复的数据进行更新 | 
| Fuzzy Filter for duplicate key | 对写入/更新的数据进行去重 | 
| Lock | 对操作的数据上锁 | 
示例
VALUES Scan & Project
mysql> explain  select abs(-1);
+-------------------------------+
| QUERY PLAN                    |
+-------------------------------+
| Project                       |
|   ->  Values Scan "*VALUES*"  |
+-------------------------------+
2 rows in set (0.00 sec)
Table Scan
mysql> explain select * from customer;
+-----------------------------------+
| QUERY PLAN                        |
+-----------------------------------+
| Project                           |
|   ->  Table Scan on tpch.customer |
+-----------------------------------+
2 rows in set (0.01 sec)
External Scan
mysql> create external table extable(n1 int)infile{"filepath"='yourpath/xx.csv'} ;
Query OK, 0 rows affected (0.03 sec)
mysql> explain select * from extable;
+------------------------------------+
| QUERY PLAN                         |
+------------------------------------+
| Project                            |
|   ->  External Scan on db1.extable |
+------------------------------------+
2 rows in set (0.01 sec)
Sink & Lock & Delete & Insert & PreInsert & Sink Scan
mysql> create table t3(n1 int);
Query OK, 0 rows affected (0.02 sec)
mysql> insert into t3 values(1);
Query OK, 1 row affected (0.01 sec)
mysql> explain update t3 set n1=2;
+-----------------------------------------------+
| QUERY PLAN                                    |
+-----------------------------------------------+
| Plan 0:                                       |
| Sink                                          |
|   ->  Lock                                    |
|         ->  Project                           |
|               ->  Project                     |
|                     ->  Table Scan on tpch.t3 |
| Plan 1:                                       |
| Delete on tpch.t3                             |
|   ->  Sink Scan                               |
|         DataSource: Plan 0                    |
| Plan 2:                                       |
| Insert on tpch.t3                             |
|   ->  Project                                 |
|         ->  PreInsert on tpch.t3              |
|               ->  Project                     |
|                     ->  Sink Scan             |
|                           DataSource: Plan 0  |
+-----------------------------------------------+
17 rows in set (0.00 sec)
Recursive Scan & CTE Scan & Filter
mysql> create table t4(n1 int,n2 int);
Query OK, 0 rows affected (0.02 sec)
mysql> insert into t4 values(1,1),(2,2),(3,3);
Query OK, 3 rows affected (0.01 sec)
mysql> explain WITH RECURSIVE t4_1(n1_1) AS (
    ->     SELECT n1 FROM t4 
    ->     UNION all
    ->     SELECT n1_1 FROM t4_1 WHERE n1_1=1
    -> )
    -> SELECT * FROM t4_1;
+---------------------------------------------------------------------------------------------------+
| QUERY PLAN                                                                                        |
+---------------------------------------------------------------------------------------------------+
| Plan 0:                                                                                           |
| Sink                                                                                              |
|   ->  Project                                                                                     |
|         ->  Table Scan on tpch.t4                                                                 |
| Plan 1:                                                                                           |
| Sink                                                                                              |
|   ->  Project                                                                                     |
|         ->  Filter                                                                                |
|               Filter Cond: (t4_1.n1_1 = 1), mo_check_level((t4_1.__mo_recursive_level_col < 100)) |
|               ->  Recursive Scan                                                                  |
|                     DataSource: Plan 2                                                            |
| Plan 2:                                                                                           |
| Sink                                                                                              |
|   ->  CTE Scan                                                                                    |
|         DataSource: Plan 0, Plan 1                                                                |
| Plan 3:                                                                                           |
| Project                                                                                           |
|   ->  Sink Scan                                                                                   |
|         DataSource: Plan 2                                                                        |
+---------------------------------------------------------------------------------------------------+
19 rows in set (0.00 sec)
Aggregate
mysql>  explain  SELECT count(*) FROM NATION group by N_NAME;
+-------------------------------------------+
| QUERY PLAN                                |
+-------------------------------------------+
| Project                                   |
|   ->  Aggregate                           |
|         Group Key: nation.n_name          |
|         Aggregate Functions: starcount(1) |
|         ->  Table Scan on tpch.nation     |
+-------------------------------------------+
5 rows in set (0.01 sec)
Join
mysql>  create table t5(n1 int);
Query OK, 0 rows affected (0.01 sec)
mysql> insert into t5 values(1),(2),(3);
Query OK, 3 rows affected (0.01 sec)
mysql> create table t6(n1 int);
Query OK, 0 rows affected (0.01 sec)
mysql> insert into t5 values(3),(4),(5);
Query OK, 3 rows affected (0.01 sec)
mysql> explain SELECT * FROM t5 LEFT JOIN t6 ON t5.n1 = t6.n1;
+------------------------------------+
| QUERY PLAN                         |
+------------------------------------+
| Project                            |
|   ->  Join                         |
|         Join Type: LEFT            |
|         Join Cond: (t5.n1 = t6.n1) |
|         ->  Table Scan on tpch.t5  |
|         ->  Table Scan on tpch.t6  |
+------------------------------------+
6 rows in set (0.00 sec)
Sample
mysql> explain SELECT SAMPLE(c_address, 90 percent) FROM customer;
+-----------------------------------------------------+
| QUERY PLAN                                          |
+-----------------------------------------------------+
| Project                                             |
|   ->  Sample                                        |
|         Sample 90.00 Percent by: customer.c_address |
|         ->  Table Scan on tpch.customer             |
+-----------------------------------------------------+
4 rows in set (0.00 sec)
SORT
mysql> explain select * from customer order by c_custkey;
+-----------------------------------------------+
| QUERY PLAN                                    |
+-----------------------------------------------+
| Project                                       |
|   ->  Sort                                    |
|         Sort Key: customer.c_custkey INTERNAL |
|         ->  Table Scan on tpch.customer       |
+-----------------------------------------------+
4 rows in set (0.00 sec)
Partition & Window
mysql>CREATE TABLE t7(n1 int,n2 int);
Query OK, 0 rows affected (0.01 sec)
mysql>  INSERT INTO t7 values(1,3),(2,2),(3,1);
Query OK, 3 rows affected (0.01 sec)
mysql> explain SELECT SUM(n1) OVER(PARTITION BY n2) AS sn1 FROM t7;
+----------------------------------------------------------+
| QUERY PLAN                                               |
+----------------------------------------------------------+
| Project                                                  |
|   ->  Window                                             |
|         Window Function: sum(t7.n1); Partition By: t7.n2 |
|         ->  Partition                                    |
|               Sort Key: t7.n2 INTERNAL                   |
|               ->  Table Scan on tpch.t7                  |
+----------------------------------------------------------+
6 rows in set (0.01 sec)
Time window & Fill
mysql> CREATE TABLE sensor_data (ts timestamp(3) primary key, temperature FLOAT);
Query OK, 0 rows affected (0.01 sec)
mysql> INSERT INTO sensor_data VALUES('2023-08-01 00:00:00', 25.0);
Query OK, 1 row affected (0.01 sec)
mysql> INSERT INTO sensor_data VALUES('2023-08-01 00:05:00', 26.0);
Query OK, 1 row affected (0.01 sec)
mysql> explain select _wstart, _wend from sensor_data  interval(ts, 10, minute)  fill(prev);
+---------------------------------------------------+
| QUERY PLAN                                        |
+---------------------------------------------------+
| Project                                           |
|   ->  Fill                                        |
|         Fill Columns:                             |
|         Fill Mode: Prev                           |
|         ->  Time window                           |
|               Sort Key: sensor_data.ts            |
|               Aggregate Functions: _wstart, _wend |
|               ->  Table Scan on db2.sensor_data   |
+---------------------------------------------------+
8 rows in set (0.00 sec)
Intersect
mysql> explain select * from t5 intersect select * from t6;
+-----------------------------------------+
| QUERY PLAN                              |
+-----------------------------------------+
| Project                                 |
|   ->  Intersect                         |
|         ->  Project                     |
|               ->  Table Scan on tpch.t5 |
|         ->  Project                     |
|               ->  Table Scan on tpch.t6 |
+-----------------------------------------+
6 rows in set (0.00 sec)
Intersect All
mysql> explain select * from t5 intersect all select * from t6;
+-----------------------------------------+
| QUERY PLAN                              |
+-----------------------------------------+
| Project                                 |
|   ->  Intersect All                     |
|         ->  Project                     |
|               ->  Table Scan on tpch.t5 |
|         ->  Project                     |
|               ->  Table Scan on tpch.t6 |
+-----------------------------------------+
6 rows in set (0.00 sec)
Minus
mysql> explain select * from t5 minus  select * from t6;
+-----------------------------------------+
| QUERY PLAN                              |
+-----------------------------------------+
| Project                                 |
|   ->  Minus                             |
|         ->  Project                     |
|               ->  Table Scan on tpch.t5 |
|         ->  Project                     |
|               ->  Table Scan on tpch.t6 |
+-----------------------------------------+
6 rows in set (0.00 sec)
Table Function
mysql>  explain select * from unnest('{"a":1}') u;
+-------------------------------------+
| QUERY PLAN                          |
+-------------------------------------+
| Project                             |
|   ->  Table Function on unnest      |
|         ->  Values Scan "*VALUES*"  |
+-------------------------------------+
3 rows in set (0.10 sec)
PreInsert UniqueKey & Fuzzy Filter for duplicate key
mysql> CREATE TABLE t8(n1 int,n2 int UNIQUE key);
Query OK, 0 rows affected (0.01 sec)
mysql> explain INSERT INTO t8(n2) values(1);
+---------------------------------------------------------------------------------+
| QUERY PLAN                                                                      |
+---------------------------------------------------------------------------------+
| Plan 0:                                                                         |
| Sink                                                                            |
|   ->  PreInsert on tpch.t8                                                      |
|         ->  Project                                                             |
|               ->  Project                                                       |
|                     ->  Values Scan "*VALUES*"                                  |
| Plan 1:                                                                         |
| Sink                                                                            |
|   ->  Lock                                                                      |
|         ->  PreInsert UniqueKey                                                 |
|               ->  Sink Scan                                                     |
|                     DataSource: Plan 0                                          |
| Plan 2:                                                                         |
| Insert on tpch.__mo_index_unique_018e2d16-6629-719d-82b5-036222e9658a           |
|   ->  Sink Scan                                                                 |
|         DataSource: Plan 1                                                      |
| Plan 3:                                                                         |
| Fuzzy Filter for duplicate key                                                  |
|   ->  Table Scan on tpch.__mo_index_unique_018e2d16-6629-719d-82b5-036222e9658a |
|         Filter Cond: (__mo_index_idx_col = 1)                                   |
|         Block Filter Cond: (__mo_index_idx_col = 1)                             |
|   ->  Sink Scan                                                                 |
|         DataSource: Plan 1                                                      |
| Plan 4:                                                                         |
| Insert on tpch.t8                                                               |
|   ->  Sink Scan                                                                 |
|         DataSource: Plan 0                                                      |
+---------------------------------------------------------------------------------+
27 rows in set (0.01 sec)
PreInsert SecondaryKey
mysql>  CREATE TABLE t9 ( n1 int , n2 int, KEY key2 (n2) USING BTREE);
Query OK, 0 rows affected (0.02 sec)
mysql>  explain INSERT INTO t9(n2) values(2);
+--------------------------------------------------------------------------+
| QUERY PLAN                                                               |
+--------------------------------------------------------------------------+
| Plan 0:                                                                  |
| Sink                                                                     |
|   ->  PreInsert on tpch.t9                                               |
|         ->  Project                                                      |
|               ->  Project                                                |
|                     ->  Values Scan "*VALUES*"                           |
| Plan 1:                                                                  |
| Insert on tpch.__mo_index_secondary_018e2d14-6f20-7db0-babb-c1fd505fd3c5 |
|   ->  Lock                                                               |
|         ->  PreInsert SecondaryKey                                       |
|               ->  Sink Scan                                              |
|                     DataSource: Plan 0                                   |
| Plan 2:                                                                  |
| Insert on tpch.t9                                                        |
|   ->  Sink Scan                                                          |
|         DataSource: Plan 0                                               |
+--------------------------------------------------------------------------+
16 rows in set (0.00 sec)