oracle 11g升级到19c后pl/sql性能下降的核心原因是统计信息不准确导致sql执行计划突变;19c优化器更依赖统计信息,对直方图缺失、采样失真等更敏感,需针对性重收集并分层响应。
oracle 11g升级到19c后pl/sql性能下降,核心原因不是pl/sql引擎本身变慢,而是底层sql执行计划突变——而统计信息不准确或过时,是触发这种突变最常见、最隐蔽的导火索。
为什么新版本更依赖统计信息
19c优化器(尤其是CBO)对统计信息的敏感度远高于11g。它默认启用更多基于代价的转换(如_optimizer_cost_based_transformation=on),一旦表的行数、列分布、直方图缺失或陈旧,优化器就容易误判选择性,比如把高区分度字段当成低区分度字段,从而放弃索引走全表扫描。
- 11g中能“蒙对”的执行计划,在19c里大概率被重写成低效路径
- 迁移时若仅用
expdp/impdp导入数据,DBMS_STATS.GATHER_SCHEMA_STATS未强制重收集,统计信息仍保留11g旧快照 - 分区表、大字段(LOB/XMLTYPE)、带函数索引等场景下,缺直方图或直方图精度不足会直接导致绑定变量窥探失效
怎么验证统计信息是否是罪魁祸首
别猜,直接查。重点盯三类对象:业务核心表、关联频繁的维度表、WHERE条件含非均匀分布字段(如状态码、类型码)的表。
- 检查统计信息最后更新时间:
SELECT owner, table_name, last_analyzed FROM dba_tables WHERE owner IN ('PROD', 'PROD_CB') AND last_analyzed - 确认直方图是否缺失:
SELECT column_name, histogram FROM dba_tab_col_statistics WHERE table_name = 'ORDER_HEADER' AND owner = 'PROD' AND histogram = 'NONE'; - 对比执行计划差异:在19c中用
EXPLAIN PLAN FOR跑慢SQL,再用SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);看是否出现TABLE ACCESS FULL替代了原INDEX RANGE SCAN
收集统计信息必须避开的坑
盲目执行DBMS_STATS.GATHER_SCHEMA_STATS可能让问题更糟——尤其当采样率、并行度、级联策略没调好时。
- 不要用
estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE在超大表上:19c默认采样逻辑更激进,可能低估高频值密度,导致直方图失真 - 避免
method_opt => 'FOR ALL COLUMNS SIZE AUTO':AUTO模式在19c中倾向少建直方图,对业务关键字段(如order_status只有'P','S','C'三种值)应显式指定SIZE 254 - 级联收集
cascade => TRUE必须配合degree => 4以上:否则索引统计信息滞后于表统计,优化器看到“表小但索引大”,反而弃用索引 - 切忌在业务高峰期执行:统计信息收集本身会锁
dba_tab_statistics元数据,可能阻塞DDL和部分DML
紧急恢复与长期策略分离处理
上线后发现慢,先止血,再根治。统计信息调整不是一锤子买卖,要分层响应。
- 紧急:对单个慢表立即重收集,锁定关键字段直方图:
EXEC DBMS_STATS.GATHER_TABLE_STATS('PROD', 'ORDER_HEADER', method_opt => 'FOR COLUMNS order_status SIZE 254', cascade => TRUE, degree => 8); - 观察:收集后立刻查
V$SQL_PLAN确认执行计划是否回退到预期路径;若未恢复,说明有hint或SPM绑定干扰,需同步检查DBA_SQL_PLAN_BASELINES - 长期:在迁移前就建立统计信息基线,用
DBMS_STATS.EXPORT_SCHEMA_STATS导出11g统计快照,升级后先导入再增量更新,避免断崖式偏差
真正麻烦的从来不是“要不要收集统计信息”,而是“收集哪几张表、哪些列、用什么参数、何时触发”。19c不会容忍模糊操作——它把统计信息从可选项变成了必答题,答错就卡住整个交易链路。











