如何使用EXPLAIN分析SQL执行计划?
在 OceanBase 中,使用 EXPLAIN 命令查看 SQL 的执行计划是进行 SQL 性能分析和优化的先决条件34。以下是具体的使用方法和分析步骤:
1. 使用不同的 EXPLAIN 模式获取执行计划
OceanBase 提供了多种 EXPLAIN 模式,以适应不同粒度的分析需求:
-
基础执行计划 (
EXPLAIN) :展示执行计划的基本信息,帮助普通用户了解整个计划的执行方式23。 -
详细执行计划 (
EXPLAIN EXTENDED) :展示最详细的执行计划,包括表的扫描范围等,通常在排查复杂问题时使用34。 -
基本执行计划 (
EXPLAIN BASIC) :用于最基本的计划展示,信息较为精简23。 -
JSON 格式输出 (
EXPLAIN FORMAT = JSON) :以 JSON 格式展示执行计划,适合进行复杂分析或程序解析。
2. 解读执行计划中的关键信息
获取执行计划后,需要重点关注输出结果中的 OPERATOR 和 NAME 列来判断 SQL 的执行逻辑:
-
查看
OPERATOR列 :- 如果显示
TABLE SCAN,表示没有走索引,正在进行全表扫描6。 - 如果显示
INDEX SCAN或INDEX SEEK,表示查询成功走了索引。 - 如果显示
TABLE GET,通常表示通过主键进行等值访问,也属于高效的索引访问方式。
- 如果显示
-
查看
NAME列 :- 如果仅显示表名或别名(如
users(t1)),通常对应全表扫描。 - 如果显示
表名(别名)索引名(如users(u),idx_user_id),则明确表示使用了指定的索引。
- 如果仅显示表名或别名(如
3. 排查未走索引的常见原因
如果发现 SQL 没有走预期的索引,可以通过以下步骤进行排查:
-
检查索引定义 :确认表上是否存在相关的索引(可使用
SHOW INDEX FROM 表名;)。 -
检查查询条件匹配度 :例如联合索引是
(a, b),但查询条件只使用了b,则无法命中索引。 -
检查隐式类型转换或函数使用 :在索引列上使用函数(如
WHERE UPPER(name) = 'ABC')或在字符串列上使用数字查询(如WHERE id = '123'),都可能导致索引失效。 -
检查统计信息 :如果怀疑优化器因为统计信息过时做出了错误决策,可以手动收集统计信息(如
ANALYZE TABLE 表名 UPDATE STATISTICS;)6。
查看语句的逻辑执行计划
very good
在 OceanBase 中,EXPLAIN 是分析 SQL 执行计划的核心工具。它能告诉你数据库会如何执行这条 SQL,比如用了哪些索引、表之间的连接顺序、以及每步的数据处理方式。
用好 EXPLAIN,是进行 SQL 调优的基本功。下面一步步来看。
第一步:基本用法
1. 查看基础执行计划
直接在 SQL 前加 EXPLAIN 即可,OceanBase 默认输出是树形文本格式(缩进代表层级):
EXPLAIN SELECT * FROM t1 WHERE id = 1;
2. 获取更详细的信息(推荐)
用 EXPLAIN EXTENDED 或 EXPLAIN 加 Hint,能看到更多优化器决策细节:
-- 查看详细计划(包括每步的谓词、表达式等)
EXPLAIN EXTENDED SELECT * FROM t1 WHERE id = 1;
-- 使用 Outline Hint 方式查看(更贴近真实执行)
EXPLAIN SELECT /*+ outline */ * FROM t1 WHERE id = 1;
第二步:读懂执行计划(关键输出字段)
执行计划会以操作符(Operator)树的形式呈现。你通常会在输出里看到这些核心信息:
| 关键部分 | 含义 | 举例 |
|---|---|---|
| ID | 操作符的执行序号,从0开始,数字越大越先执行(即最内层先执行) |
ID 2 会比 ID 1 先执行 |
| OPERATOR | 具体的操作类型,如 TABLE SCAN、NESTED-LOOP JOIN、SORT
|
TABLE SCAN(全表扫描)或 TABLE GET(主键点查) |
| NAME | 操作的对象,通常是表名或索引名 |
t1 或 t1_idx1
|
| EST. ROWS | 优化器估算的该步返回的行数(用于判断估算是否准确) | 100 |
| COST | 优化器估算的该步执行代价(数值越小通常越快) | 152.3 |
示例输出:
| ========================================
| ID | OPERATOR | NAME | EST. ROWS | COST |
| ---|-------------|------|-----------|------|
| 0 | TABLE SCAN | t1 | 1 | 12.5 |
| ========================================
第三步:常见操作符解读
看懂操作符,你就知道 SQL 的大致执行路径了:
-
TABLE GET:通过主键精准获取一行,效率极高,是最理想的点查。 -
TABLE SCAN:全表扫描,意味着要读取表中所有数据,通常效率较低(除非小表)。 -
INDEX SCAN:扫描索引表,能避免回表(索引包含所需字段)时效率很高。 -
NESTED-LOOP JOIN:嵌套循环连接,适用于驱动表很小或被驱动表有索引的场景。 -
HASH JOIN:哈希连接,适用于大表关联且无合适索引的场景,会消耗内存。 -
MERGE JOIN:归并连接,连接键已有序时使用。 -
SORT:显式排序操作,若数据量大可能产生磁盘落盘,较耗资源。
第四步:查看真实执行信息(与 EXPLAIN 区分)
EXPLAIN 只是预估,要查看 SQL 真实执行的统计信息(如实际扫描行数、耗时),需要用:
-- 先开启会话级统计信息收集(只需执行一次)
SET SESSION ob_enable_trace_log = ON;
-- 执行你的 SQL
SELECT * FROM t1 WHERE id = 1;
-- 查看真实执行统计信息(重点关注物理读、扫描行数)
SHOW TRACE;
对比 EXPLAIN 估算的 EST. ROWS 和 SHOW TRACE 里的实际扫描行数,是发现统计信息过期(导致选错计划)的常见方法。