在Oracle数据库的日常运维和开发工作中,SQL查询的执行效率直接影响整个系统的响应速度,而分析query plan也就是执行计划,是排查SQL性能问题最核心、最直接的方式。通过执行计划可以清楚看到Oracle执行一条SQL时的完整路径,包括表的访问方式、表之间的连接顺序、是否使用索引等信息,从而快速定位性能瓶颈。

获取Oracle query plan的常用方法
Oracle提供了多种获取执行计划的方式,不同场景下可以选择合适的方法:
1. 使用EXPLAIN PLAN命令
这是最常用的获取执行计划的方式,不需要实际执行SQL,适合在不想触发真实查询的场景下分析。基本语法如下:
-- 生成执行计划到plan_table EXPLAIN PLAN FOR SELECT * FROM users u JOIN orders o ON u.user_id = o.user_id WHERE u.age > 18 AND o.status = 'PAID'; -- 查看执行计划 SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
2. 使用AUTOTRACE功能
在SQL*Plus或者一些客户端工具中,可以开启AUTOTRACE功能,执行SQL的同时自动输出执行计划和统计信息,适合需要同时查看执行效果和性能统计的场景:
-- 开启AUTOTRACE,显示执行计划和结果 SET AUTOTRACE ON -- 执行目标SQL SELECT * FROM users WHERE user_name = '张三'; -- 关闭AUTOTRACE SET AUTOTRACE OFF
3. 查询动态性能视图
如果SQL已经在数据库中执行过,可以从动态性能视图中获取真实的执行计划,这种方式获取的是SQL实际执行时的计划,更准确:
-- 查询最近执行的SQL的游标信息,获取sql_id
SELECT sql_id, sql_text FROM v$sqlarea WHERE sql_text LIKE '%SELECT * FROM users%';
-- 根据sql_id查看真实执行计划
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('替换为实际sql_id', NULL, 'ALLSTATS LAST'));query plan关键内容解读
拿到执行计划后,需要先理解各个部分的含义,才能准确判断性能问题:
执行顺序
执行计划是缩进格式展示的,缩进越多的步骤越先执行,同一缩进层级的步骤从上到下执行。比如下面的执行计划片段,先执行全表扫描USERS表,再执行全表扫描ORDERS表,最后做哈希连接:
------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| ------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 50 | 6 (0)| |* 1 | HASH JOIN | | 1 | 50 | 6 (0)| |* 2 | TABLE ACCESS FULL| USERS | 5 | 100 | 3 (0)| |* 3 | TABLE ACCESS FULL| ORDERS| 10 | 200 | 3 (0)| -------------------------------------------------------------------
核心指标含义
执行计划中几个关键指标需要重点关注:
- Operation:执行的操作类型,比如TABLE ACCESS FULL表示全表扫描,INDEX RANGE SCAN表示索引范围扫描,HASH JOIN表示哈希连接。
- Name:操作对应的对象名称,比如表名、索引名。
- Rows:Oracle预估的该步骤返回的行数,如果和实际返回行数差距很大,说明统计信息可能过期。
- Cost:Oracle估算的执行该步骤的资源消耗,数值越低代表消耗越少。
通过query plan定位性能问题
结合执行计划的内容,可以快速定位常见的SQL性能问题:
1. 全表扫描问题
如果执行计划中出现TABLE ACCESS FULL,且对应的表数据量很大,Rows预估很高,说明可能没有合适的索引。这时候可以检查查询条件中的字段是否有索引,如果没有可以添加对应索引:
-- 为users表的age字段添加索引,优化年龄查询的全表扫描问题 CREATE INDEX idx_users_age ON users(age);
2. 索引失效问题
如果查询条件中用了函数、隐式类型转换,会导致索引失效,执行计划依然走全表扫描。比如下面的查询对user_name字段用了UPPER函数,即使user_name有索引也不会生效:
-- 索引失效的写法 SELECT * FROM users WHERE UPPER(user_name) = 'ZHANGSAN'; -- 优化后的写法,避免对索引字段使用函数 SELECT * FROM users WHERE user_name = '张三';
3. 连接顺序不合理
多表连接时如果小表和大表的连接顺序不合理,也会导致性能问题。Oracle的执行计划会显示连接的顺序,一般应该让小表作为驱动表,减少连接的数据量。如果发现连接顺序不合理,可以通过添加提示来固定连接顺序:
-- 使用LEADING提示指定驱动表为users小表 SELECT /*+ LEADING(u) */ * FROM users u JOIN orders o ON u.user_id = o.user_id WHERE u.age > 18;
执行计划分析注意事项
分析query plan时还需要注意几个问题:执行计划的Rows是预估数据,如果发现和实际执行返回的行数差距超过30%,应该先收集表的统计信息,再重新生成执行计划;测试环境的执行计划和生产环境可能因为数据量不同而有差异,生产环境的问题优先看真实执行计划;不要盲目相信执行计划的Cost数值,最终还是要以SQL的实际执行时间为准。
Oraclequery_planSQL优化执行计划修改时间:2026-06-06 23:41:15