千家信息网

读懂执行计划

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,查看执行计划的方法Explain Plan For SQL• 不实际执行SQL语句,生成的计划未必是真实执行的计划• 必须要有plan_table是一种手段但不是最好的SQLPLUS AUTOTRAC
千家信息网最后更新 2026年11月01日读懂执行计划



查看执行计划的方法

  1. Explain Plan For SQL
    • 不实际执行SQL语句,生成的计划未必是真实执行的计划
    • 必须要有plan_table
    是一种手段但不是最好的
  2. SQLPLUS AUTOTRACE
    • 除set autotrace traceonly explain外均实际执行SQL,但仍未必
    是真实计划
    • 必须要有plan_table
  3. SQL TRACE
    • 需要启用10046戒者SQL_TRACE
    • 一般用tkprof看的更清楚些,当然10046里本身也有执行计划信息
  4. V$SQL和V$SQL_PLAN
    • 可以查询到多个子游标的计划信息了,但是看起来比较费劲
  5. Enterprise Manager
    • 可以图形化显示执行计划,但并非所有环境有EM可用
  6. 其他第三方工具
    • 注意 PL/SQL developer之类工具F5看到的执行计划未必是真实的

D:\instantclient_12_2>sqlplus scott/tiger@clonepdb_plug

SQL*Plus: Release 12.2.0.1.0 Production on Fri Jan 12 13:54:31 2018

Copyright (c) 1982, 2016, Oracle. All rights reserved.

Last Successful login time: Fri Jan 12 2018 11:18:59 +08:00

Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production

SCOTT@clonepdb_plug>set linesize 180
SCOTT@clonepdb_plug>set pagesize 0
SCOTT@clonepdb_plug>alter session set STATISTICS_LEVEL = ALL;

Session altered.

SCOTT@clonepdb_plug>select * from emp where ename='SMITH';
7369 SMITH CLERK 7902 1980-12-17 00:00:00 800 20

SCOTT@clonepdb_plug>select * from table(dbms_xplan.display_cursor(null,null,'allstats'));
SQL_ID cgf95c3k5mszx, child number 0

select * from emp where ename='SMITH'

Plan hash value: 3956160932


| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |

| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 8 |
|* 1 | TABLE ACCESS FULL| EMP | 1 | 1 | 1 |00:00:00.01 | 8 |

Predicate Information (identified by operation id):

1 - filter("ENAME"='SMITH')

18 rows selected.

SCOTT@clonepdb_plug>

需要授权
grant select on v$session to scott;
grant select on v
$sql to scott;
grant select on v_$sqlplan to scott;
grant select on v
$sql_plan_statistics_all to scott;

  1. 基本字段(总是可用的)

Id 执行计划中每一个操作(行)的标识符。如果数字前面带有星号,意味着将在随后提供这行包含的谓词信息
Operation 对应执行的操作。也叫行源操作
Name 操作的对象名称
2.查询优化器评估信息

Rows(E-Rows) 预估操作返回的记录条数
Bytes(E-Bytes) 预估操作返回的记录字节数
TempSpc 预估操作使用临时表空间的大小
Cost(%CPU) 预估操作所需的开销。在括号中列出了CPU开销的百分比。注意这些值是通过执行计划计算出来的。换句话说,父操作的开销包含子操作的开销
Time 预估执行操作所需要的时间(HH:MM:SS)
3.分区(仅当访问分区表时下列字段可见)

Pstart 访问的第一个分区。如果解析时不知道是哪个分区就设为KEY,KEY(I),KEY(MC),KEY(OR),KEY(SQ)
Pstop 访问的最后一个分区。如果解析时不知道是哪个分区就设为KEY,KEY(I),KEY(MC),KEY(OR),KEY(SQ)
4.并行和分布式处理(仅当使用并行或分布式操作时下列字段可见)

Inst 在分布式操作中,指操作使用的数据库链接的名字
TQ 在并行操作中,用于从属线程间通信的表队列
IN-OUT 并行或分布式操作间的关系
PQ Distrib 在并行操作中,生产者为发送数据给消费者进行的分配
5.运行时统计(当设定参数statistics_level为all或使用gather_plan_statistics提示时,下列字段可见)

Starts 指定操作执行的次数
A-Rows 操作返回的真实记录数
A-Time 操作执行的真实时间(HH:MM:SS.FF)
6.I/O 统计(当设定参数statistics_level为all或使用gather_plan_statistics提示时,下列字段可见)

Buffers 执行期间进行的逻辑读操作数量
Reads 执行期间进行的物理读操作数量
Writes 执行期间进行的物理写操作数量
7.内存使用统计

OMem 最优执行所需内存的预估值
1Mem 一次通过(one-pass)执行所需内存的预估值
0/1/M 最优/一次通过/多次通过(multipass)模式操作执行的次数
Used-Mem 最后一次执行时操作使用的内存量
Used-Tmp 最后一次执行时操作使用的临时空间大小。这个字段必须扩大1024倍才能和其他衡量内存的字段一致(比如,32k意味着32MB)
Max-Tmp 操作使用的最大临时空间大小。这个字段必须扩大1024倍才能和其他衡量内存的字段一致(比如,32k意味着32MB)
例
SCOTT@clonepdb_plug>explain plan for
2 select * from emp e,dept d
3 where e.deptno=d.deptno
4 and e.ename='SMITH';

Explained.

SCOTT@clonepdb_plug>select from table(dbms_xplan.display(null,null,'advanced'));
Plan hash value: 3625962092 -----是指执行计划转成的hash值,和执行效率无关,执行计划的唯一标示
/
执行计划部分*/

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

| 0 | SELECT STATEMENT | | 1 | 59 | 4 (0)| 00:00:01 |
| 1 | NESTED LOOPS | | 1 | 59 | 4 (0)| 00:00:01 |
| 2 | NESTED LOOPS | | 1 | 59 | 4 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL | EMP | 1 | 39 | 3 (0)| 00:00:01 |
|
4 | INDEX UNIQUE SCAN | PK_DEPT | 1 | | 0 (0)| 00:00:01 |
| 5 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 | 20 | 1 (0)| 00:00:01 |

Query Block Name / Object Alias (identified by operation id): --这部分显示的为查询块名和对象别名

3 - SEL$1 / E@SEL$1 -E@SEL$1,对应到执行计划中的操作ID为3上,即在表E上的查询,E为别名,下面类同 SEL$为select 的缩写,位于块1,相应的还有DEL$,INS$,UPD$等
4 - SEL$1 / D@SEL$1
5 - SEL$1 / D@SEL$1

Outline Data --提纲部分,这部分将执行计划中的图形化方式以文本形式来呈现,即转换为提示符方式

/+
BEGIN_OUTLINE_DATA
NLJ_BATCHING(@"SEL$1" "D"@"SEL$1") --指示优化器以嵌套循环关联预提取的方式访问表
USE_NL(@"SEL$1" "D"@"SEL$1") --使用USE_NL提示,即嵌套循环
LEADING(@"SEL$1" "E"@"SEL$1" "D"@"SEL$1") --指明前导表
INDEX(@"SEL$1" "D"@"SEL$1" ("DEPT"."DEPTNO"))-指明对于D上的访问方式为使用索引
FULL(@"SEL$1" "E"@"SEL$1") --指明对于E上的访问方式为全表扫描 OUTLINE_LEAF(@"SEL$1")
br/>OUTLINE_LEAF(@"SEL$1")

DB_VERSION('12.2.0.1')
OPTIMIZER_FEATURES_ENABLE('12.2.0.1')
IGNORE_OPTIM_EMBEDDED_HINTS
END_OUTLINE_DATA
/

Predicate Information (identified by operation id):--谓词信息部分,在执行计划中ID带有星号的每一行均对应到下面中的一行

3 - filter("E"."ENAME"='SMITH')
4 - access("E"."DEPTNO"="D"."DEPTNO")

Column Projection Information (identified by operation id):--执行时每一步骤所返回的列,下面的不同步骤返回了不同的列

1 - (#keys=0) "E"."EMPNO"[NUMBER,22], "E"."ENAME"[VARCHAR2,10],
"E"."JOB"[VARCHAR2,9], "E"."MGR"[NUMBER,22], "E"."HIREDATE"[DATE,7],
"E"."SAL"[NUMBER,22], "E"."COMM"[NUMBER,22], "E"."DEPTNO"[NUMBER,22],
"D"."DEPTNO"[NUMBER,22], "D"."DNAME"[VARCHAR2,14], "D"."LOC"[VARCHAR2,13]
2 - (#keys=0) "E"."EMPNO"[NUMBER,22], "E"."ENAME"[VARCHAR2,10],
"E"."JOB"[VARCHAR2,9], "E"."MGR"[NUMBER,22], "E"."HIREDATE"[DATE,7],
"E"."SAL"[NUMBER,22], "E"."COMM"[NUMBER,22], "E"."DEPTNO"[NUMBER,22],
"D".ROWID[ROWID,10], "D"."DEPTNO"[NUMBER,22]
3 - "E"."EMPNO"[NUMBER,22], "E"."ENAME"[VARCHAR2,10], "E"."JOB"[VARCHAR2,9],
"E"."MGR"[NUMBER,22], "E"."HIREDATE"[DATE,7], "E"."SAL"[NUMBER,22],
"E"."COMM"[NUMBER,22], "E"."DEPTNO"[NUMBER,22]
4 - "D".ROWID[ROWID,10], "D"."DEPTNO"[NUMBER,22]
5 - "D"."DNAME"[VARCHAR2,14], "D"."LOC"[VARCHAR2,13]

Note--注释与描述部分,下面的描述中给出了本次SQL语句使用了动态采样功能

  • this is an adaptive plan

64 rows selected.
例
SCOTT@clonepdb_plug>select /+ gather_plan_statistics / * from emp e,dept d
2 where e.deptno=d.deptno
3 and e.ename='SMITH';
--注意此处增加了提示gather_plan_statistics并且该语句被执行 等同于alter session set STATISTICS_LEVEL = ALL;
7369 SMITH CLERK 7902 1980-12-17 00:00:00 800 20 20 RESEARCH
DALLAS

SCOTT@clonepdb_plug>select * from table(dbms_xplan.display_cursor(null,null,'iostats last'));--使用display_cursor获取实际的执行计划
SQL_ID 0wb0wwb3621n2, child number 0 --这部分给出了SQL语句的SQL_ID,子游标号以及原始的SQL语句

select /+ gather_plan_statistics / * from emp e,dept d
where e.deptno=d.deptno and e.ename='SMITH'

Plan hash value: 3625962092


| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |

| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 9 |
| 1 | NESTED LOOPS | | 1 | 1 | 1 |00:00:00.01 | 9 |
| 2 | NESTED LOOPS | | 1 | 1 | 1 |00:00:00.01 | 8 |
| 3 | TABLE ACCESS FULL | EMP | 1 | 1 | 1 |00:00:00.01 | 7 |
|
4 | INDEX UNIQUE SCAN | PK_DEPT | 1 | 1 | 1 |00:00:00.01 | 1 |
| 5 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 | 1 | 1 |00:00:00.01 | 1 |

Predicate Information (identified by operation id):

3 - filter("E"."ENAME"='SMITH')
4 - access("E"."DEPTNO"="D"."DEPTNO")

Note

  • this is an adaptive plan
    28 rows selected.

    SCOTT@clonepdb_plug>select * from table(dbms_xplan.display_cursor('6h2msdzb5hj7s',null,'ADVANCED peeked_binds ALLSTATS'));
    SQL_ID 6h2msdzb5hj7s, child number 0

    select /+ gather_plan_statistics / * from emp e,dept d
    where e.deptno=d.deptno and rownum<20 and ename like
    '%I%'

Plan hash value: 2662388210


| Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers | OMem | 1Mem | O/1/M |

| 0 | SELECT STATEMENT | | 1 | | | 4 (100)| | 4 |00:00:00.02 | 15 | | | |
| 1 | COUNT STOPKEY | | 1 | | | | | 4 |00:00:00.02 | 15 | | | |
|
2 | HASH JOIN | | 1 | 1 | 59 | 4 (0)| 00:00:01 | 4 |00:00:00.02 | 15 | 1055K| 1055K| 1/0/0|
|* 3 | TABLE ACCESS FULL| EMP | 1 | 1 | 39 | 3 (0)| 00:00:01 | 4 |00:00:00.01 | 7 | | | |
| 4 | TABLE ACCESS FULL| DEPT | 1 | 1 | 20 | 1 (0)| 00:00:01 | 3 |00:00:00.01 | 8 | | | |

Query Block Name / Object Alias (identified by operation id):

1 - SEL$1
3 - SEL$1 / E@SEL$1
4 - SEL$1 / D@SEL$1

Outline Data

/+
BEGIN_OUTLINE_DATA
FULL(@"SEL$1" "D"@"SEL$1")
USE_HASH(@"SEL$1" "D"@"SEL$1")IGNORE_OPTIM_EMBEDDED_HINTS
OPTIMIZER_FEATURES_ENABLE('12.2.0.1')
DB_VERSION('12.2.0.1')
ALL_ROWS
OUTLINE_LEAF(@"SEL$1")
br/>IGNORE_OPTIM_EMBEDDED_HINTS
OPTIMIZER_FEATURES_ENABLE('12.2.0.1')
DB_VERSION('12.2.0.1')
ALL_ROWS
OUTLINE_LEAF(@"SEL$1")

LEADING(@"SEL$1" "E"@"SEL$1" "D"@"SEL$1")
END_OUTLINE_DATA
/

Predicate Information (identified by operation id):

1 - filter(ROWNUM<20)
2 - access("E"."DEPTNO"="D"."DEPTNO")
3 - filter(("ENAME" LIKE '%I%' AND "ENAME" IS NOT NULL))

Column Projection Information (identified by operation id):

1 - "E"."DEPTNO"[NUMBER,22], "D"."DEPTNO"[NUMBER,22], "E"."EMPNO"[NUMBER,22], "ENAME"[VARCHAR2,10], "E"."JOB"[VARCHAR2,9],
"E"."MGR"[NUMBER,22], "E"."HIREDATE"[DATE,7], "E"."SAL"[NUMBER,22], "E"."COMM"[NUMBER,22], "D"."LOC"[VARCHAR2,13],
"D"."DEPTNO"[NUMBER,22], "D"."DNAME"[VARCHAR2,14], "D"."LOC"[VARCHAR2,13], "D"."DNAME"[VARCHAR2,14]
2 - (#keys=1) "E"."DEPTNO"[NUMBER,22], "D"."DEPTNO"[NUMBER,22], "E"."EMPNO"[NUMBER,22], "ENAME"[VARCHAR2,10], "E"."JOB"[VARCHAR2,9],
"E"."MGR"[NUMBER,22], "E"."HIREDATE"[DATE,7], "E"."SAL"[NUMBER,22], "E"."COMM"[NUMBER,22], "D"."LOC"[VARCHAR2,13],
"D"."DEPTNO"[NUMBER,22], "D"."DNAME"[VARCHAR2,14], "D"."LOC"[VARCHAR2,13], "D"."DNAME"[VARCHAR2,14]
3 - "E"."EMPNO"[NUMBER,22], "ENAME"[VARCHAR2,10], "E"."JOB"[VARCHAR2,9], "E"."MGR"[NUMBER,22], "E"."HIREDATE"[DATE,7],
"E"."SAL"[NUMBER,22], "E"."COMM"[NUMBER,22], "E"."DEPTNO"[NUMBER,22]
4 - "D"."DEPTNO"[NUMBER,22], "D"."DNAME"[VARCHAR2,14], "D"."LOC"[VARCHAR2,13]

Note

  • this is an adaptive plan

66 rows selected.

SCOTT@clonepdb_plug>





字段 内存 信息 方式 语句 提示 分布式 开销 部分 查询 大小 实际 意味 执行期 数量 空间 不同 一致 一行 别名 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 科技互联网龙头 中国 科技 互联网 美国互联网科技 深圳互联网络科技有限公司 鑫亿盛互联网科技 互联网科技logo设计 广州紫鲸互联网科技 互联网高科技企业 深圳艾佳互联网科技 一五八零互联网科技 银川新华互联网科技学校地址 中盈科技互联网信息有限公司 小米互联网科技园设置 重庆互联网医院沙龙医盟信息科技 崇明区互联网教育科技诚信经营 米聚互联网科技南京有限公司排面 梅州GM互联网络科技有限公司 从那以后互联网科技有限公司 云鲸互联网络科技有限公司 中国科技和美国互联网 广州百单互联网科技有限公司 互联网科技实习生岗位职责 花神(南京)互联网科技有限公司 浙南科技城互联网大厦建设工程 特约风豹互联网科技为什么扣费 中和天地互联网科技有限公司 杭州披云加互联网科技有限公司 南京一网一红互联网科技有限公司 互联网科技企业商标注意事项 前海云享互联网科技
0