
好的,我们来全面深入地解析 Oracle 19c 数据库中一个专门用于诊断查询优化器行为的会话级视图:V$SES_OPTIMIZER_ENV。
V$SES_OPTIMIZER_ENV 提供了会话级别的优化器环境设置。它揭示了影响 SQL 查询优化器(CBO)为特定会话生成执行计划的所有参数和设置。当同一个 SQL 语句在不同会话中产生不同的执行计划时,这个视图是查找根本原因的“终极武器”。
一、字段含义详解
V$SES_OPTIMIZER_ENV 的字段清晰地描述了优化器环境的各个维度。以下是所有字段的详细说明:
| 字段名 | 数据类型 | 描述 | 重要说明与解读 |
|---|---|---|---|
| SID | NUMBER | 会话标识符 (Session Identifier)。 | 与 V$SESSION.SID 直接对应,是关联会话上下文的关键。 |
| ID | NUMBER | 优化器环境参数的内部唯一标识符。 | 此ID与 V$SQL_OPTIMIZER_ENV 中的 ID 对应,用于精确匹配参数。通常不需要直接使用。 |
| NAME | VARCHAR2(80) | 优化器环境参数的名称。这是最有用的字段。 | 例如:"optimizer_mode", "optimizer_index_cost_adj", "optimizer_features_enable", "parallel_degree_policy"。 |
| VALUE | VARCHAR2(512) | 该环境参数在此会话中的当前有效值。 | 这是核心数据。它显示了该会话的实际生效值,这可能与系统级参数 (V$PARAMETER.VALUE) 不同。 |
| ISDEFAULT | VARCHAR2(9) | 指示该参数的会话值是否为默认值。 | 取值为 'YES' 或 'NO'。'NO' 是排查的重点,它表示该参数在会话级别被显式修改过(如通过 ALTER SESSION)。 |
| DEFAULT_VALUE | VARCHAR2(512) | 该参数的系统级默认值。 | 用于与 VALUE 字段对比,快速识别差异。 |
核心优化器环境参数 (NAME) 举例:
| 参数名称 (NAME) | 示例值 (VALUE) | 描述与性能影响 |
|---|---|---|
optimizer_mode | ALL_ROWS, FIRST_ROWS_N | 优化器目标。ALL_ROWS 倾向于全量吞吐量,FIRST_ROWS_N 倾向于首批响应速度。这是导致执行计划差异的常见原因。 |
optimizer_features_enable | 19.1.0, 12.2.0.1 | 启用的优化器功能集。将其设置为旧版本可能会禁用某些新特性,导致生成旧的执行计划。 |
optimizer_index_cost_adj | 100 (default), 50 | 调整索引访问成本的权重。值<100使优化器更倾向于选择索引扫描。随意修改此参数非常危险。 |
optimizer_index_caching | 0 (default), 90 | 告知优化器索引块在缓存中的百分比。高值使其更倾向于索引嵌套循环连接。 |
parallel_degree_policy | MANUAL, AUTO | 并行度策略。设置为 AUTO 允许Oracle自动决定并行度。 |
"_optimizer_adaptive_plans" | TRUE, FALSE | 控制是否允许自适应执行计划(19c 重要特性)。以下划线 _ 开头通常表示隐藏参数。 |
"_optimizer_use_feedback" | TRUE, FALSE | 控制是否使用SQL计划指导反馈。 |
"cursor_sharing" | EXACT, FORCE | 控制字面替换(绑定变量)行为。FORCE 可能导致执行计划不理想。 |
二、核心原理与底层机制
1. 数据来源与底层基表
V$SES_OPTIMIZER_ENV 的数据来源于 每个会话的 PGA (Program Global Area) 或 UGA (User Global Area) 中的私有内存结构。优化器环境是会话上下文的一部分,独立于其他会话。
其底层源是 X$ 表,通常是 X$QESMMOSENV 或类似的底层结构。这些 X$ 表提供了对会话私有内存的直接映射。
- 工作原理:
- 会话初始化:当一个新的会话建立时,它会继承当前实例的优化器系统参数设置(如
optimizer_modefromV$PARAMETER)。 - 会话修改:会话可以使用
ALTER SESSION SET ...命令覆盖任何可修改的优化器参数(如ALTER SESSION SET optimizer_mode = FIRST_ROWS_10;)。这个新值会存储在会话的私有PGA/UGA中。 - SQL 解析:每当会话解析一条新的 SQL 语句时,优化器 (CBO) 会读取该会话的私有优化器环境(即此视图所显示的内容),并使用这些设置来评估各种执行路径的成本,最终生成一个执行计划。
- 实时查询:查询
V$SES_OPTIMIZER_ENV即直接读取该会话PGA中的这些设置值。 - 会话终止:会话结束时,其私有内存被释放,记录消失。
- 会话初始化:当一个新的会话建立时,它会继承当前实例的优化器系统参数设置(如
2. 为什么优化器环境至关重要?
Oracle 的基于成本的优化器 (CBO) 不是一个在真空中工作的绝对实体。它的行为由数百个参数和环境设置共同控制。两个完全相同的数据库实例,如果优化器环境设置不同,对于同一条 SQL 语句,可能会生成两个完全不同的、性能差异巨大的执行计划。
V$SES_OPTIMIZER_ENV 提供了洞察这一“决策上下文”的能力。它回答了:“在为我生成执行计划时,优化器到底看到了什么?”
3. 与 V$SQL_OPTIMIZER_ENV 的关系
这是两个极易混淆但至关重要的视图:
V$SES_OPTIMIZER_ENV:显示会话当前的优化器环境设置。这些设置将用于该会话接下来要解析的所有新 SQL 语句。V$SQL_OPTIMIZER_ENV:显示在过去的某个时间点,当优化器为一条特定的、已存在于共享池中的 SQL 语句生成执行计划时,所使用的历史优化器环境设置。- 简单说:
V$SES_是现在和将来,V$SQL_是过去。 - 当一条SQL的执行计划表现异常时,应查询
V$SQL_OPTIMIZER_ENV来追溯它当初被编译时的环境。
- 简单说:
三、常用查询 SQL 示例
-
查看某个会话(SID=123)的所有非默认优化器设置(排查的首选查询)
SELECT sid, name, value, isdefault, default_value FROM v$ses_optimizer_env WHERE sid = 123 AND isdefault = 'NO' -- 重点排查被修改过的参数! ORDER BY name; -
比较两个会话(SID 100 和 200)的优化器环境差异
SELECT name, MAX(CASE sid WHEN 100 THEN value END) AS sid_100_value, MAX(CASE sid WHEN 100 THEN isdefault END) AS sid_100_default, MAX(CASE sid WHEN 200 THEN value END) AS sid_200_value, MAX(CASE sid WHEN 200 THEN isdefault END) AS sid_200_default FROM v$ses_optimizer_env WHERE sid IN (100, 200) GROUP BY name HAVING MAX(CASE sid WHEN 100 THEN value END) <> MAX(CASE sid WHEN 200 THEN value END) OR (MAX(CASE sid WHEN 100 THEN value END) IS NULL AND MAX(CASE sid WHEN 200 THEN value END) IS NOT NULL) OR (MAX(CASE sid WHEN 100 THEN value END) IS NOT NULL AND MAX(CASE sid WHEN 200 THEN value END) IS NULL) ORDER BY name; -
查找所有修改了危险参数
optimizer_index_cost_adj的会话SELECT s.sid, s.username, s.program, s.osuser, env.value AS current_setting, env.default_value, s.sql_id, s.prev_sql_id FROM v$ses_optimizer_env env JOIN v$session s ON env.sid = s.sid WHERE env.name = 'optimizer_index_cost_adj' AND env.isdefault = 'NO' -- 只查找被修改的会话 ORDER BY env.value; -
检查当前会话自身的优化器模式(
optimizer_mode)SELECT name, value, isdefault FROM v$ses_optimizer_env WHERE sid = (SELECT sid FROM v$mystat WHERE rownum = 1) AND name = 'optimizer_mode'; -
综合查询:关联会话信息,查看关键优化器参数
SELECT s.sid, s.username, s.program, env1.name, env1.value, env1.isdefault, env2.name, env2.value, env2.isdefault FROM v$session s LEFT JOIN v$ses_optimizer_env env1 ON s.sid = env1.sid AND env1.name = 'optimizer_mode' LEFT JOIN v$ses_optimizer_env env2 ON s.sid = env2.sid AND env2.name = 'optimizer_features_enable' WHERE s.type = 'USER' AND s.status = 'ACTIVE';
四、主要应用场景
-
诊断执行计划差异(Plan Disparity):
这是最核心的用途。当报告“同一个SQL在不同程序/会话中性能不同”时,DBA 可以比较两个会话的V$SES_OPTIMIZER_ENV,快速识别出是否是optimizer_mode、optimizer_features_enable等关键参数设置不一致导致的。 -
排查由于应用配置引起的性能问题:
某些应用程序框架或连接池会在会话建立后执行ALTER SESSION语句来修改优化器环境。通过此视图可以确认应用是否做了此类修改,以及修改的值是否合理。 -
验证参数更改效果:
在会话中执行ALTER SESSION后,立即查询此视图可以确认更改是否已成功生效。 -
审计和历史分析:
结合监控工具定期采集此视图的数据,可以审计哪些会话修改了关键的优化器参数,用于事后的问题分析和安全审计。 -
性能优化:
在进行SQL调优时,了解会话的优化器环境是第一步。有时,简单地将会话的optimizer_mode从ALL_ROWS改为FIRST_ROWS_N就能极大地改善交互式应用的响应速度。
五、相关视图
V$SESSION:必须关联的视图。提供会话的基本信息(用户、程序、当前SQL等)。V$SQL_OPTIMIZER_ENV:极其重要。提供SQL语句在被解析时所使用的历史优化器环境。用于解释为什么某条SQL是现在这个执行计划。V$SQL/V$SQLAREA:用于通过SQL_ID获取SQL文本和执行计划。当从V$SES_OPTIMIZER_ENV发现问题后,需要关联此视图查看会话正在执行的SQL。V$PARAMETER:显示系统级的初始化参数值。V$SES_OPTIMIZER_ENV.DEFAULT_VALUE通常与此视图的VALUE字段一致。DBA_HIST_SQL_OPTIMZR_ENV:AWR 历史快照中的V$SQL_OPTIMIZER_ENV数据,用于历史回溯分析。
总结:V$SES_OPTIMIZER_ENV 是 Oracle DBA 解决“执行计划飘忽不定”这类复杂性能问题的照明弹。它深入到了优化器决策机制的核心层面,揭示了会话级的配置差异。熟练掌握这个视图,意味着你不仅能看到执行计划是什么(DBMS_XPLAN),更能理解它为什么会是这样,从而能够进行精准的、根本原因层面的诊断和优化。
欢迎关注我的公众号《IT小Chen》

被折叠的 条评论
为什么被折叠?



