EXPLAIN

The EXPLAIN statement shows the execution plan for a query without executing it. It complements the EXPLAIN ANALYZE statement, which executes the query. If the output of EXPLAIN does not match the expected result, consider executing ANALYZE TABLE on each table in the query to make sure the table statistics are up to date.

The statements DESC and DESCRIBE are aliases of this statement. The alternative usage of EXPLAIN <tableName> is documented under SHOW [FULL] COLUMNS FROM.

TiDB supports the EXPLAIN [options] FOR CONNECTION connection_id statement. However, this statement is different from the EXPLAIN FOR statement in MySQL. For more details, see EXPLAIN FOR CONNECTION.

Synopsis

ExplainSym

EXPLAIN - 图1

ExplainStmt

EXPLAIN - 图2

ExplainableStmt

EXPLAIN - 图3

  1. ExplainSym ::=
  2. 'EXPLAIN'
  3. | 'DESCRIBE'
  4. | 'DESC'
  5. ExplainStmt ::=
  6. ExplainSym ( TableName ColumnName? | 'ANALYZE'? ExplainableStmt | 'FOR' 'CONNECTION' NUM | 'FORMAT' '=' ( stringLit | ExplainFormatType ) ( 'FOR' 'CONNECTION' NUM | ExplainableStmt ) )
  7. ExplainableStmt ::=
  8. SelectStmt
  9. | DeleteFromStmt
  10. | UpdateStmt
  11. | InsertIntoStmt
  12. | ReplaceIntoStmt
  13. | UnionStmt

EXPLAIN output format

EXPLAIN - 图4

Note

When you use the MySQL client to connect to TiDB, to read the output result in a clearer way without line wrapping, you can use the pager less -S command. Then, after the EXPLAIN result is output, you can press the right arrow → button on your keyboard to horizontally scroll through the output.

EXPLAIN - 图5

Note

In the returned execution plan, for all probe-side child nodes of IndexJoin and Apply operators, the meaning of estRows since v6.4.0 is different from that before v6.4.0. You can find details in TiDB Query Execution Plan Overview.

Currently, EXPLAIN in TiDB outputs 5 columns: id, estRows, task, access object, operator info. Each operator in the execution plan is described by these attributes, with each row in the EXPLAIN output describing an operator. The description of each attribute is as follows:

Attribute nameDescription
idThe operator ID is the unique identifier of the operator in the entire execution plan. In TiDB 2.1, the ID is formatted to display the tree structure of the operator. Data flows from the child node to the parent node. One and only one parent node for each operator.
estRowsThe number of rows that the operator is expected to output. This number is estimated according to the statistics and the operator’s logic. estRows is called count in the earlier versions of TiDB 4.0.
taskThe type of task the operator belongs to. Currently, the execution plans are divided into two tasks: root task, which is executed on tidb-server, and cop task, which is performed in parallel on TiKV or TiFlash. The topology of the execution plan at the task level is that a root task followed by many cop tasks. The root task uses the output of cop tasks as input. The cop tasks refer to tasks that TiDB pushes down to TiKV or TiFlash. Each cop task is distributed in the TiKV cluster or the TiFlash cluster, and is executed by multiple processes.
access objectData item information accessed by the operator. The information includes table, partition, and index (if any). Only operators that directly access the data have such information.
operator infoOther information about the operator. operator info of each operator is different. You can refer to the following examples.

Examples

  1. EXPLAIN SELECT 1;
  1. +-------------------+---------+------+---------------+---------------+
  2. | id | estRows | task | access object | operator info |
  3. +-------------------+---------+------+---------------+---------------+
  4. | Projection_3 | 1.00 | root | | 1->Column#1 |
  5. | └─TableDual_4 | 1.00 | root | | rows:1 |
  6. +-------------------+---------+------+---------------+---------------+
  7. 2 rows in set (0.00 sec)
  1. CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL);
  1. Query OK, 0 rows affected (0.10 sec)
  1. INSERT INTO t1 (c1) VALUES (1), (2), (3);
  1. Query OK, 3 rows affected (0.02 sec)
  2. Records: 3 Duplicates: 0 Warnings: 0
  1. EXPLAIN SELECT * FROM t1 WHERE id = 1;
  1. +-------------+---------+------+---------------+---------------+
  2. | id | estRows | task | access object | operator info |
  3. +-------------+---------+------+---------------+---------------+
  4. | Point_Get_1 | 1.00 | root | table:t1 | handle:1 |
  5. +-------------+---------+------+---------------+---------------+
  6. 1 row in set (0.00 sec)
  1. DESC SELECT * FROM t1 WHERE id = 1;
  1. +-------------+---------+------+---------------+---------------+
  2. | id | estRows | task | access object | operator info |
  3. +-------------+---------+------+---------------+---------------+
  4. | Point_Get_1 | 1.00 | root | table:t1 | handle:1 |
  5. +-------------+---------+------+---------------+---------------+
  6. 1 row in set (0.00 sec)
  1. DESCRIBE SELECT * FROM t1 WHERE id = 1;
  1. +-------------+---------+------+---------------+---------------+
  2. | id | estRows | task | access object | operator info |
  3. +-------------+---------+------+---------------+---------------+
  4. | Point_Get_1 | 1.00 | root | table:t1 | handle:1 |
  5. +-------------+---------+------+---------------+---------------+
  6. 1 row in set (0.00 sec)
  1. EXPLAIN INSERT INTO t1 (c1) VALUES (4);
  1. +----------+---------+------+---------------+---------------+
  2. | id | estRows | task | access object | operator info |
  3. +----------+---------+------+---------------+---------------+
  4. | Insert_1 | N/A | root | | N/A |
  5. +----------+---------+------+---------------+---------------+
  6. 1 row in set (0.00 sec)
  1. EXPLAIN UPDATE t1 SET c1=5 WHERE c1=3;
  1. +---------------------------+---------+-----------+---------------+--------------------------------+
  2. | id | estRows | task | access object | operator info |
  3. +---------------------------+---------+-----------+---------------+--------------------------------+
  4. | Update_4 | N/A | root | | N/A |
  5. | └─TableReader_8 | 0.00 | root | | data:Selection_7 |
  6. | └─Selection_7 | 0.00 | cop[tikv] | | eq(test.t1.c1, 3) |
  7. | └─TableFullScan_6 | 3.00 | cop[tikv] | table:t1 | keep order:false, stats:pseudo |
  8. +---------------------------+---------+-----------+---------------+--------------------------------+
  9. 4 rows in set (0.00 sec)
  1. EXPLAIN DELETE FROM t1 WHERE c1=3;
  1. +---------------------------+---------+-----------+---------------+--------------------------------+
  2. | id | estRows | task | access object | operator info |
  3. +---------------------------+---------+-----------+---------------+--------------------------------+
  4. | Delete_4 | N/A | root | | N/A |
  5. | └─TableReader_8 | 0.00 | root | | data:Selection_7 |
  6. | └─Selection_7 | 0.00 | cop[tikv] | | eq(test.t1.c1, 3) |
  7. | └─TableFullScan_6 | 3.00 | cop[tikv] | table:t1 | keep order:false, stats:pseudo |
  8. +---------------------------+---------+-----------+---------------+--------------------------------+
  9. 4 rows in set (0.01 sec)

To specify the format of the EXPLAIN output, you can use the FORMAT = xxx syntax. Currently, TiDB supports the following formats:

FORMATDescription
Not specifiedIf the format is not specified, EXPLAIN uses the default format row.
briefThe operator IDs in the output of the EXPLAIN statement are simplified, compared with those when FORMAT is left unspecified.
dotThe EXPLAIN statement outputs DOT execution plans, which can be used to generate PNG files through a dot program (in the graphviz package).
rowThe EXPLAIN statement outputs results in a tabular format. See Understand the Query Execution Plan for more information.
tidb_jsonThe EXPLAIN statement outputs execution plans in JSON and stores the operator information in a JSON array.
verboseThe EXPLAIN statement outputs results in the row format, with an additional estCost column for the estimated cost of the query in the results. For more information about how to use this format, see SQL Plan Management.
plan_cacheThe EXPLAIN statement outputs results in the row format, with the Plan Cache information as a warning.
  • brief
  • DotGraph
  • JSON

The following is an example when FORMAT is "brief" in EXPLAIN:

  1. EXPLAIN FORMAT = "brief" DELETE FROM t1 WHERE c1 = 3;
  1. +-------------------------+---------+-----------+---------------+--------------------------------+
  2. | id | estRows | task | access object | operator info |
  3. +-------------------------+---------+-----------+---------------+--------------------------------+
  4. | Delete | N/A | root | | N/A |
  5. | └─TableReader | 0.00 | root | | data:Selection |
  6. | └─Selection | 0.00 | cop[tikv] | | eq(test.t1.c1, 3) |
  7. | └─TableFullScan | 3.00 | cop[tikv] | table:t1 | keep order:false, stats:pseudo |
  8. +-------------------------+---------+-----------+---------------+--------------------------------+
  9. 4 rows in set (0.001 sec)

In addition to the MySQL standard result format, TiDB also supports DotGraph and you need to specify FORMAT = "dot" as in the following example:

  1. CREATE TABLE t(a bigint, b bigint);
  2. EXPLAIN format = "dot" SELECT A.a, B.b FROM t A JOIN t B ON A.a > B.b WHERE A.a < 10;
  1. +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
  2. | dot contents |
  3. +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
  4. |
  5. digraph Projection_8 {
  6. subgraph cluster8{
  7. node [style=filled, color=lightgrey]
  8. color=black
  9. label = "root"
  10. "Projection_8" -> "HashJoin_9"
  11. "HashJoin_9" -> "TableReader_13"
  12. "HashJoin_9" -> "Selection_14"
  13. "Selection_14" -> "TableReader_17"
  14. }
  15. subgraph cluster12{
  16. node [style=filled, color=lightgrey]
  17. color=black
  18. label = "cop"
  19. "Selection_12" -> "TableFullScan_11"
  20. }
  21. subgraph cluster16{
  22. node [style=filled, color=lightgrey]
  23. color=black
  24. label = "cop"
  25. "Selection_16" -> "TableFullScan_15"
  26. }
  27. "TableReader_13" -> "Selection_12"
  28. "TableReader_17" -> "Selection_16"
  29. }
  30. |
  31. +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
  32. 1 row in set (0.00 sec)

If your computer has a dot program, you can generate a PNG file using the following method:

  1. dot xx.dot -T png -O
  2. The xx.dot is the result returned by the above statement.

If your computer has no dot program, copy the result to this website to get a tree diagram:

Explain Dot

To get the output in JSON, specify FORMAT = "tidb_json" in the EXPLAIN statement. The following is an example:

  1. CREATE TABLE t(id int primary key, a int, b int, key(a));
  2. EXPLAIN FORMAT = "tidb_json" SELECT id FROM t WHERE a = 1;
  1. +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
  2. | TiDB_JSON |
  3. +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
  4. | [
  5. {
  6. "id": "Projection_4",
  7. "estRows": "10.00",
  8. "taskType": "root",
  9. "operatorInfo": "test.t.id",
  10. "subOperators": [
  11. {
  12. "id": "IndexReader_6",
  13. "estRows": "10.00",
  14. "taskType": "root",
  15. "operatorInfo": "index:IndexRangeScan_5",
  16. "subOperators": [
  17. {
  18. "id": "IndexRangeScan_5",
  19. "estRows": "10.00",
  20. "taskType": "cop[tikv]",
  21. "accessObject": "table:t, index:a(a)",
  22. "operatorInfo": "range:[1,1], keep order:false, stats:pseudo"
  23. }
  24. ]
  25. }
  26. ]
  27. }
  28. ]
  29. |
  30. +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
  31. 1 row in set (0.01 sec)

In the output, id, estRows, taskType, accessObject, and operatorInfo have the same meaning as the columns in the default format. subOperators is an array that stores the sub-nodes. The fields and meanings of the sub-nodes are the same as the parent node. If a field is missing, it means that the field is empty.

MySQL compatibility

  • Both the format of EXPLAIN and the potential execution plans in TiDB differ substantially from MySQL.
  • TiDB does not support the FORMAT=JSON or FORMAT=TREE options.
  • FORMAT=tidb_json in TiDB is the JSON format output of the default EXPLAIN result. The format and fields are different from the FORMAT=JSON output in MySQL.

EXPLAIN FOR CONNECTION

EXPLAIN FOR CONNECTION is used to get the execution plan of the currently executed SQL query or the last executed SQL query in a connection. The output format is the same as that of EXPLAIN. However, the implementation of EXPLAIN FOR CONNECTION in TiDB is different from that in MySQL. Their differences (apart from the output format) are listed as follows:

  • If the connection is sleeping, MySQL returns an empty result, while TiDB returns the last executed query plan.
  • If you try to get the execution plan of the current session, MySQL returns an error, while TiDB returns the result normally.
  • MySQL requires the login user to be the same as the connection being queried, or the login user has the PROCESS privilege; while TiDB requires the login user to be the same as the connection being queried, or the login user has the SUPER privilege.

See also