Oracle 19c实时统计对PL/SQL优化无直接作用,仅影响DML后SQL硬解析的基数估算;PL/SQL静态SQL复用游标依赖传统DBMS_STATS统计,仅EXECUTE IMMEDIATE动态SQL在触发硬解析时才可能间接受益。
DBMS_STATS 不支持在 PL/SQL 中“实现实时统计信息搜集”——这不是一个可编程调用的功能,也不是 PL/SQL 能主动触发或控制的机制。
Oracle 19c 的实时统计信息(Real-Time Statistics)是**内核级自动行为**,仅在满足特定条件的 DML 操作(如 INSERT、UPDATE、DELETE)执行后,由 Oracle 后台进程隐式更新部分统计字段(如 NUM_ROWS、NUM_DISTINCT),且**仅限 Exadata 环境默认启用**。非 Exadata 环境需手动设置隐藏参数,生产环境严禁使用。
实时统计不是 PL/SQL 可调用的 API
你无法在 pl/sql 块里写 dbms_stats.gather_table_stats 或类似调用来“开启实时收集”。它不提供 pl/sql 接口;也没有 dbms_stats.gather_realtime_stats 这样的函数。所谓“新特性”,是指优化器在解析 sql 时能读取这些轻量字段,而非供开发者显式调用。
如何确认实时统计是否生效(而不是“怎么用”)
检查 DBA_TAB_STATISTICS 或 DBA_TAB_COL_STATISTICS 的 NOTES 列是否含 'STATS_ON_CONVENTIONAL_DML':
SELECT TABLE_NAME, NOTES, SCOPE FROM DBA_TAB_STATISTICS WHERE OWNER = 'SH' AND TABLE_NAME = 'SALES';
- 若
NOTES为空,说明尚未发生触发实时更新的 DML,或当前环境未启用该特性 - 若值为
'STATS_ON_CONVENTIONAL_DML',仅表示“曾有过 DML 触发记录”,不代表当前值已被优化器采纳——必须配合硬解析才起作用 -
SCOPE = 'SHARED'表示该统计被多个会话共享,但 PL/SQL 游标复用仍依赖传统统计
PL/SQL 中误用实时统计的典型错误
常见误解包括:
- 在 PL/SQL 中执行
INSERT后立刻查DBA_TAB_STATISTICS,看到NUM_ROWS变了,就认为后续SELECT会自动走更好执行计划——但静态 SQL 复用游标,根本不会重解析 - 用
EXECUTE IMMEDIATE拼接 SQL 并期待“每次都能受益”,却忽略:若拼出的 SQL 文本重复(如固定 WHERE 条件),仍可能软解析复用旧计划,绕过实时值 - 禁用自动统计任务(
auto optimizer stats collection)后,以为实时统计能“顶上”,结果发现直方图、CLUSTERING_FACTOR、索引统计全缺失,JOIN 顺序严重错乱
DBMS_STATS.GATHER_TABLE_STATS 收集的完整统计(含直方图、列关联性、索引叶块数等)。实时统计只是一层极窄的补充,且仅对硬解析生效——而 PL/SQL 的性能瓶颈,往往卡在游标复用逻辑、集合绑定方式、或执行计划稳定性上,不在这里。











