Skip to content

EXPLAIN Output Format

Output Structure

The syntax structure execution result is a textual description of the plan selected for the statement, optionally annotated with execution statistics.

The following is an example of an output structure using query analysis of a dataset in 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 输出一个名 EXPLAIN outputs a tree structure named QUERY PLAN, with each leaf node containing the node type, affected objects. We will now only use node type information to simplify the presentation of the example above. The QUERY PLAN tree visualizes the entire process of a SQL query, showing the nodes through which it operates.

Project
└── Filter
    └── Join
        └── Table Scan
        └── Table Scan

Node Type

MatrixOne supports the following node types.

Node name meaning
Values Scan Scanning of processed values
Table Scan Scanning data from a table
External Scan Handling external data scanning
Source Scan Processing a data scan of the source table
Project Projective operations on data
Sink Distribute the same data to one / more objects
Sink Scan Read data distributed by other objects
Recursive Scan In the loop CTE syntax, the data at the end of each loop is processed to determine whether to open the next round of looping
CTE Scan Loop CTE syntax to read the data at the beginning of each loop
Aggregate Aggregation of data
Filter Filtering of data
Join Concatenation of data
Sample SAMPLE Sampling function to sample the data
Sort Sorting data
Partition Sorting data in the range window and slicing by value
Union Combining result sets for two or more queries
Union All Combination of result sets for two or more queries, including duplicate rows
Window Perform range window calculations on data
Time Window Perform time window calculations on data
Fill Handling NULL values in the time window
Insert Insertion of data
Delete Deletion of data
Intersect Combination of rows that exist for two or more queries
Intersect All Combination of rows that exist for two or more queries, including duplicate rows.
Minus Compares the results of two queries and returns the rows that exist in the first query but not in the second query
Table Function Reading data through table functions
PreInsert Organize the data to be written
PreInsert UniqueKey Organize the data to be written to the unique key hidden table
PreInsert SecondaryKey Organize the data to be written to the secondary index hidden table
PreDelete Organize the data that needs to be deleted from the partitioned table.
On Duplicate Key Updates to duplicate data
Fuzzy Filter for duplicate key De-duplication of written/updated data
Lock Locking the data of an operation

Example

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)