EXPLAIN PLAN对比执行路径是最基础可靠的优化判断方式,需清空共享池后分别执行并比对Operation和Cost列,辅以AUTOTRACE获取真实统计,再结合V$SQL历史快照与SQL Monitor细粒度分析验证稳定性。

用 EXPLAIN PLAN 看执行路径差异
直接对比两条SQL的执行计划,是最基础也最可靠的判断方式。Oracle不会告诉你“快了还是慢了”,但会暴露关键路径变化:是否从全表扫描变成索引访问、连接顺序是否调整、是否引入了NESTED LOOPS或HASH JOIN等开销不同的操作。
- 先清空计划缓存:
ALTER SYSTEM FLUSH SHARED_POOL;(仅测试环境可用,生产慎用) - 对优化前和优化后的SQL分别执行:
EXPLAIN PLAN FOR SELECT ...,再查SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY); - 重点比对
Operation列和Cost列——Cost值下降50%以上通常意味着实质性改进,但要注意:它只是估算值,不等于真实耗时 - 如果看到
TABLE ACCESS FULL消失、替换成INDEX RANGE SCAN或INDEX UNIQUE SCAN,基本说明索引被有效利用
抓真实执行统计:SET AUTOTRACE ON STATISTICS
比EXPLAIN PLAN更进一步,它返回真实运行时的资源消耗数据,比如逻辑读、物理读、执行次数——这些才是性能瓶颈的直接证据。
- 确保用户有
PLUSTRACE角色:GRANT PLUSTRACE TO your_user;,否则会报错SP2-0618: Cannot find the Session Identifier - 在SQL*Plus或SQL Developer中执行:
SET AUTOTRACE ON STATISTICS,再跑SQL;结果里重点关注consistent gets(逻辑读)和physical reads(物理IO) - 示例中一条SQL优化后
consistent gets从17355138降到23412,哪怕Elapsed Time没变,也说明内存压力大幅缓解 - 注意:
recursive calls突然升高,可能意味着优化引入了隐式类型转换或视图展开,反而增加解析负担
查V$SQL获取历史执行快照
如果你没法重跑SQL(比如线上已上线),就只能从共享池里捞历史执行记录。这个方法适合回溯性对比,但依赖SQL文本完全一致(空格、大小写、绑定变量都要匹配)。
- 用
SQL_ID定位语句:SELECT SQL_ID, SQL_TEXT FROM V$SQL WHERE SQL_TEXT LIKE '%xstfxps2%'; - 查两次执行的统计:
SELECT ELAPSED_TIME/1000000 AS sec, BUFFER_GETS, EXECUTIONS FROM V$SQL WHERE SQL_ID = 'xxx'; -
BUFFER_GETS除以EXECUTIONS得出单次平均逻辑读,比绝对值更有可比性 - 如果
IS_BIND_SENSITIVE='YES',说明该SQL存在绑定变量窥探问题,不同参数可能导致执行计划漂移——此时单看一次执行结果不可靠
别只盯Elapsed Time,DB Time和CPU Time才见真章
用户感知的“慢”,常被归因于Elapsed Time,但它包含等待时间(如db file sequential read)。真正反映SQL自身效率的是CPU Time和DB Time(数据库内部消耗总和)。
- 用
DBMS_SQLTUNE.REPORT_SQL_MONITOR(需启用监控)看细粒度分解,例如某次执行Elapsed Time=3.2s,但DB Time=0.8s,说明大量时间花在锁等待或网络传输上,不是SQL本身问题 - 如果优化后
CPU Time下降而Elapsed Time不变,大概率是IO等待被掩盖了——要继续查IO Wait Events,比如direct path read是否减少 - 特别注意
Rows Processed与Executions的比值:如果处理行数翻倍但Buffer Gets只增20%,说明访问路径确实更高效
真实环境里,EXPLAIN PLAN和AUTOTRACE能快速定位方向,但V$SQL和SQL Monitor才能确认优化是否稳定生效——尤其当SQL走自适应执行计划或受绑定变量影响时,单次测试容易误判。



















