在SQLPlus中查看执行计划需先执行EXPLAIN PLAN FOR语句将计划写入PLAN_TABLE,再运行SELECT FROM TABLE(DBMS_XPLAN.DISPLAY(...))查询;常用DISPLAY显示预估计划,DISPLAY_CURSOR显示已执行SQL的真实计划及实际统计信息。
SQL*Plus 里直接看执行计划用什么命令
在 oracle 中,explain plan 不是函数也不是视图,它是个语句级指令,必须先执行它把计划写进 plan_table,再查出来。很多人输完 explain plan for select ... 就以为完事了,结果一查 plan_table 是空的——因为没执行 select * from table(dbms_xplan.display)。
常见错误现象:ORA-00942: table or view does not exist(没建 PLAN_TABLE)、查出空结果(忘了调 DBMS_XPLAN.DISPLAY)、看到旧计划(没清表,重复执行没覆盖)。
- 先确保有
PLAN_TABLE:运行@?/rdbms/admin/utlxplan.sql(DBA 用户)或CREATE TABLE PLAN_TABLE AS SELECT * FROM PLAN_TABLE$(普通用户) - 执行计划前加
EXPLAIN PLAN SET STATEMENT_ID = 'my_query' FOR,方便后续按 ID 过滤 - 立刻跟一句
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY(NULL, 'my_query', 'ALL')),'ALL'能显示谓词、绑定变量、分区裁剪等关键信息,比默认'TYPICAL'更有用
长 SQL 放不进 SQL*Plus 怎么办
SQL*Plus 默认行宽 80 字符,超长 SQL 直接被截断或报 SP2-0027: input is too long。这不是语法问题,是客户端限制。
使用场景:从应用日志或 AWR 抓出来的带几十个子查询、上百行的 SQL,想原样分析执行计划。
- 改用
sqlplus -S / as sysdba启动时加-S(silent mode)能缓解部分截断,但治标不治本 - 更可靠的是把 SQL 写进文件,用
@/path/to/sqlfile.sql执行;注意文件末尾别留空行,否则EXPLAIN PLAN可能只读到一半 - 如果 SQL 含换行符和注释,优先用
DBMS_SQL.PARSE+DBMS_XPLAN.DISPLAY_CURSOR(需已执行过),避免手动拼接
DBMS_XPLAN.DISPLAY_CURSOR 和 DISPLAY 有什么区别
DISPLAY 看的是 EXPLAIN PLAN 静态生成的计划,不反映真实执行路径;DISPLAY_CURSOR 看的是刚执行过的 SQL 在共享池里的实际计划,含真实代价、I/O 统计、自适应计划分支等。
性能影响:用 DISPLAY_CURSOR 不会重解析,但要求 SQL 已在 V$SQL 里,且未被老化出共享池。对长 SQL 来说,如果执行太慢或失败,它根本不会进 V$SQL,这时只能退回到 DISPLAY。
- 查刚跑完的长 SQL:用
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('sql_id', child_number, 'ALLSTATS LAST')),'ALLSTATS LAST'显示上次执行的实际行数、缓冲区读取等,比预估更准 - 如果 SQL 执行超时或被 kill,
V$SQL里可能没有记录,此时DISPLAY_CURSOR返回空,得切回DISPLAY+STATEMENT_ID -
child_number别硬写 0,用SELECT sql_id, child_number FROM V$SQL WHERE sql_text LIKE '%...%'先确认
为什么看懂执行计划比写 SQL 还难
Oracle 执行计划里嵌套深、缩进靠空格、操作符含义模糊(比如 NESTED LOOPS 不一定快,FULL 不一定慢),加上统计信息不准、绑定变量窥探失效、自适应计划动态切换,同一段 SQL 在不同环境可能走完全不同的路径。
容易被忽略的地方:计划里出现 VIEW 或 UNION-ALL 节点时,往往意味着优化器把子查询做了物化或重写,原始 SQL 的结构已经失真;Predicate Information 里带 access 和 filter 的条件,执行顺序和代价差异极大,但文本里混在一起很难分辨。
真正卡住人的不是怎么查计划,而是查完之后看不懂哪一行在拖慢整条链路——这时候得结合 Rows 列(预估 vs 实际)、Starts(循环次数)、A-Rows(实际返回行数)交叉比对,而不是盯着 Cost 数字看。










