📣

TiDB Cloud Serverless 现已更名为
Starter
!此页面由 AI 自动翻译,英文原文请见
此处。

EXPLAIN

EXPLAIN 语句用于展示查询的执行计划,但不会实际执行该查询。它与会实际执行查询的 EXPLAIN ANALYZE 语句互为补充。如果 EXPLAIN 的输出结果与预期不符,建议对查询中涉及的每个表执行 ANALYZE TABLE,以确保表统计信息是最新的。

DESCDESCRIBE 语句是 EXPLAIN 语句的别名。EXPLAIN <tableName> 的另一种用法已在 SHOW [FULL] COLUMNS FROM 中记录。

TiDB 支持 EXPLAIN [options] FOR CONNECTION connection_id 语句。但该语句与 MySQL 中的 EXPLAIN FOR 语句不同。详情请参见 EXPLAIN FOR CONNECTION

语法

ExplainSym
EXPLAINDESCRIBEDESC
ExplainStmt
ExplainSymTableNameColumnNameANALYZEExplainableStmtFORCONNECTIONNUMFORMAT=stringLitExplainFormatTypeFORCONNECTIONNUMExplainableStmt
ExplainableStmt
SelectStmtDeleteFromStmtUpdateStmtInsertIntoStmtReplaceIntoStmtUnionStmt

EXPLAIN 输出格式

目前,TiDB 中的 EXPLAIN 输出包含 5 列:idestRowstaskaccess objectoperator info。执行计划中的每个算子都由这些属性描述,EXPLAIN 输出的每一行描述一个算子。各属性说明如下:

属性名描述
id算子 ID,是整个执行计划中该算子的唯一标识。在 TiDB 2.1 中,ID 的格式用于展示算子的树形结构。数据流从子节点流向父节点。每个算子有且仅有一个父节点。
estRows算子预计输出的行数。该数值根据统计信息和算子逻辑进行估算。estRows 在 TiDB 4.0 早期版本中称为 count
task算子所属的任务类型。目前,执行计划分为两类任务:root 任务(在 tidb-server 上执行)和 cop 任务(在 TiKV 或 TiFlash 上并行执行)。执行计划在任务层级的拓扑结构为一个 root 任务后接多个 cop 任务。root 任务以 cop 任务的输出为输入。cop 任务指 TiDB 下推到 TiKV 或 TiFlash 的任务。每个 cop 任务分布在 TiKV 集群或 TiFlash 集群中,由多个进程执行。
access object算子访问的数据项信息。信息包括 tablepartitionindex(如有)。只有直接访问数据的算子才有该信息。
operator info算子的其他信息。每个算子的 operator info 不同,可参考下方示例。

示例

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

你可以通过 FORMAT = xxx 语法指定 EXPLAIN 输出的格式。目前,TiDB 支持以下几种格式:

FORMAT描述
未指定如果未指定格式,EXPLAIN 使用默认的 row 格式。
brief与未指定 FORMAT 时相比,EXPLAIN 语句输出中的算子 ID 更为简化。
dotEXPLAIN 语句输出 DOT 执行计划,可通过 dot 程序(在 graphviz 包中)生成 PNG 文件。
rowEXPLAIN 语句以表格形式输出结果。更多信息参见 理解查询执行计划
tidb_jsonEXPLAIN 语句以 JSON 格式输出执行计划,并将算子信息存储在 JSON 数组中。
verboseEXPLAIN 语句以 row 格式输出结果,并在结果中增加 estCost 列,显示查询的估算成本。关于如何使用该格式,参见 SQL 执行计划管理
plan_cacheEXPLAIN 语句以 row 格式输出结果,并以警告形式输出 Plan Cache 信息。
cost_traceEXPLAIN 语句以扩展的 row 格式输出结果,增加两列:estCost(估算成本)和 costFormula(成本公式)。

    以下为 EXPLAINFORMAT"brief" 时的示例:

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

    除了 MySQL 标准的结果格式外,TiDB 还支持 DotGraph,你需要像下面这样指定 FORMAT = "dot"

    CREATE TABLE t(a bigint, b bigint); EXPLAIN format = "dot" SELECT A.a, B.b FROM t A JOIN t B ON A.a > B.b WHERE A.a < 10;
    +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | dot contents | +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | digraph Projection_8 { subgraph cluster8{ node [style=filled, color=lightgrey] color=black label = "root" "Projection_8" -> "HashJoin_9" "HashJoin_9" -> "TableReader_13" "HashJoin_9" -> "Selection_14" "Selection_14" -> "TableReader_17" } subgraph cluster12{ node [style=filled, color=lightgrey] color=black label = "cop" "Selection_12" -> "TableFullScan_11" } subgraph cluster16{ node [style=filled, color=lightgrey] color=black label = "cop" "Selection_16" -> "TableFullScan_15" } "TableReader_13" -> "Selection_12" "TableReader_17" -> "Selection_16" } | +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)

    如果你的电脑已安装 dot 程序,可以通过以下方式生成 PNG 文件:

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

    如果你的电脑没有安装 dot 程序,可以将结果复制到 此网站 以获得树状图:

    Explain Dot

    如需以 JSON 格式输出结果,在 EXPLAIN 语句中指定 FORMAT = "tidb_json"。示例如下:

    CREATE TABLE t(id int primary key, a int, b int, key(a)); EXPLAIN FORMAT = "tidb_json" SELECT id FROM t WHERE a = 1;
    +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | TiDB_JSON | +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | [ { "id": "Projection_4", "estRows": "10.00", "taskType": "root", "operatorInfo": "test.t.id", "subOperators": [ { "id": "IndexReader_6", "estRows": "10.00", "taskType": "root", "operatorInfo": "index:IndexRangeScan_5", "subOperators": [ { "id": "IndexRangeScan_5", "estRows": "10.00", "taskType": "cop[tikv]", "accessObject": "table:t, index:a(a)", "operatorInfo": "range:[1,1], keep order:false, stats:pseudo" } ] } ] } ] | +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.01 sec)

    在输出中,idestRowstaskTypeaccessObjectoperatorInfo 的含义与默认格式下的列相同。subOperators 是一个数组,用于存储子节点。子节点的字段及含义与父节点一致。如果某个字段缺失,表示该字段为空。

    MySQL 兼容性

    • TiDB 中 EXPLAIN 的格式及可能的执行计划与 MySQL 有较大差异。
    • TiDB 不支持 FORMAT=JSONFORMAT=TREE 选项。
    • TiDB 中的 FORMAT=tidb_json 是默认 EXPLAIN 结果的 JSON 格式输出,其格式和字段与 MySQL 的 FORMAT=JSON 输出不同。

    EXPLAIN FOR CONNECTION

    EXPLAIN FOR CONNECTION 用于获取某个连接当前正在执行的 SQL 查询或上一次执行的 SQL 查询的执行计划。输出格式与 EXPLAIN 相同。但 TiDB 中 EXPLAIN FOR CONNECTION 的实现与 MySQL 不同。两者的区别(除输出格式外)如下:

    • 如果连接处于 sleeping 状态,MySQL 返回空结果,而 TiDB 返回上一次执行的查询计划。
    • 如果你尝试获取当前会话的执行计划,MySQL 会返回错误,而 TiDB 会正常返回结果。
    • MySQL 要求登录用户与被查询连接的用户相同,或登录用户拥有 PROCESS 权限;而 TiDB 要求登录用户与被查询连接的用户相同,或登录用户拥有 SUPER 权限。

    另请参阅

    文档内容是否有帮助?