Oracle用户需获v_$sql_plan查询权限才能查V$SQL_PLAN;EXPLAIN PLAN+DBMS_XPLAN.DISPLAY用于预估计划;V$SQL_PLAN查真实执行路径但依赖SQL已执行且未老化;绑定变量场景推荐SQL Monitor获取含统计的实时计划。

执行计划查不到?先确认 Oracle 用户有 V$SQL_PLAN 查询权限
很多 Java 应用连上 Oracle 后调 EXPLAIN PLAN FOR ... 能成功,但查 PLAN_TABLE 为空,或直接查 V$SQL_PLAN 报 ORA-00942: table or view does not exist —— 根本原因通常是数据库用户缺少视图访问权限。DBA 通常只给应用用户 SELECT_CATALOG_ROLE,但这不自动包含 V$ 动态性能视图权限。
必须由 DBA 执行:
GRANT SELECT ON v_$sql_plan TO your_app_user;
注意:v_$sql_plan 是底层基表,V$SQL_PLAN 是同义词,授权时要用带下划线的 v_$ 形式。没这个权限,后续所有 JDBC 查询都只能看到空结果或报错。
用 EXPLAIN PLAN FOR + DBMS_XPLAN.DISPLAY 获取可读计划(适合预估)
这是最常用、最可控的方式,适用于你手上有慢 SQL 文本,想快速看优化器预估路径,不依赖真实执行。JDBC 中需分两步:先解释,再查输出。
立即学习“Java免费学习笔记(深入)”;
- 第一步:执行
EXPLAIN PLAN FOR SELECT ...(注意不能带分号,且必须是单条语句) - 第二步:用
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY())拉出格式化文本 -
DBMS_XPLAN.DISPLAY支持参数如'PLAN_TABLE'、'ALL',但默认即查当前会话最新 plan,够用 - JDBC 中建议用
PreparedStatement执行EXPLAIN PLAN,避免 SQL 注入;但DBMS_XPLAN.DISPLAY必须用Statement,因为它返回的是多列字符串结果集
示例关键代码片段:
conn.prepareStatement("EXPLAIN PLAN FOR SELECT * FROM orders WHERE status = ?").execute();
ResultSet rs = conn.createStatement().executeQuery(
"SELECT PLAN_TABLE_OUTPUT FROM TABLE(DBMS_XPLAN.DISPLAY())");
while (rs.next()) {
System.out.println(rs.getString(1));
}查 V$SQL_PLAN 获取真实执行计划(需已执行且未被老化)
如果 SQL 已在生产中跑过,且你想看它**实际走的路径**(比如是否用了绑定变量窥探后的错误索引),就得查 V$SQL_PLAN。但它只保留共享池中还存活的 cursor 计划,受 shared_pool 大小和 LRU 策略影响,可能几分钟后就没了。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
关键点:
- 先通过
V$SQL找到目标 SQL 的SQL_ID,常用过滤条件是SQL_TEXT LIKE '%your_keyword%'或按ELAPSED_TIME排序 -
V$SQL_PLAN的ID和PARENT_ID构成树结构,需递归或用LEVEL+CONNECT BY展开(Oracle 10g+ 支持) - JDBC 中推荐用如下 SQL 一次性拉平(避免客户端拼树):
SELECT LPAD(' ', 2*(LEVEL-1)) || OPERATION || ' ' || OPTIONS || ' ' || OBJECT_NAME AS PLAN_LINE
FROM V$SQL_PLAN
WHERE SQL_ID = ?
START WITH ID = 0
CONNECT BY PRIOR ID = PARENT_ID AND SQL_ID = PRIOR SQL_ID注意:此查询需在有 V$SQL_PLAN 权限的前提下执行,且 SQL_ID 必须精确匹配(大小写敏感,不可用模糊查询)。
绑定变量让 EXPLAIN PLAN 失效?用 DBMS_SQLTUNE.REPORT_SQL_MONITOR 替代
当 SQL 含绑定变量(如 WHERE id = ?),EXPLAIN PLAN FOR 默认用 NULL 或类型默认值做硬解析,计划可能和真实执行天差地别。这时 V$SQL_PLAN 更可靠,但前提是 SQL 已执行过。
更优解是启用 SQL 监控(需 Oracle 11g+ 企业版 + STATISTICS_LEVEL=ALL):
- 确保 SQL 执行时加了
/*+ MONITOR */提示,或满足自动监控阈值(如执行时间 > 5 秒) - 执行后立即查
DBMS_SQLTUNE.REPORT_SQL_MONITOR,它返回 XML 或 TEXT 格式的真实运行时计划,含 A-Rows(实际返回行数)、Buffers、Reads 等诊断关键指标 - JDBC 中调用方式为
CallableStatement执行函数:
{ ? = call DBMS_SQLTUNE.REPORT_SQL_MONITOR(
sql_id => ?,
type => 'TEXT',
report_level => 'ALL') }返回的 CLOB 字符串就是带颜色标记(HTML 模式)或缩进清晰(TEXT 模式)的完整监控报告,比纯 V$SQL_PLAN 多出执行统计维度。
真实执行计划的获取永远依赖“SQL 是否已跑过”和“计划是否还在内存里”,没有银弹。最稳妥的组合是:开发期用 EXPLAIN PLAN 快速验证,上线后靠 SQL Monitor 抓现场,再辅以定期采样 V$SQL_PLAN 建立慢 SQL 基线。

















