本文目录导读:

这是一个非常专业且重要的问题。数据库版本升级后,查询优化器(Query Optimizer)的算法和内部逻辑可能发生了改变,旧的统计信息无法准确反映新版本优化器的需求,甚至可能误导它,导致生成低效的执行计划。
下面从几个核心原因详细解释:
优化器算法和成本模型可能改变
这是最根本的原因,数据库的查询优化器负责为SQL语句选择“最优”的执行计划(走索引还是全表扫描,使用哪种Join算法等),它主要依赖两样东西:
- 统计信息:描述数据分布的特征。
- 成本模型:一个用于计算不同执行计划“代价”的数学公式。
升级带来的变化:
- 新算法:新版本可能引入了新的Join算法(如Hash Join的变种)、新的索引访问方式(如Skip Scan)或更智能的基数估算逻辑,旧统计信息的设计初衷并非为了支持这些新算法,因此无法提供新算法所需的精确数据(新的直方图类型)。
- 成本计算公式调整:不同版本数据库对CPU成本、I/O成本、内存成本、网络成本的权重定义可能完全不同,旧统计信息按照旧成本模型计算出的“最优”计划,在新成本模型下可能恰恰是“最差”的计划。
举个栗子:旧版本认为“全表扫描”成本高,因为I/O权重很大,新版本优化了I/O,并降低了其成本权重,认为“索引扫描+回表”在某些情况下成本更高,如果统计信息陈旧,优化器可能仍按旧模型选择代价高昂的索引扫描。
基数和数据分布估算可能严重失准
统计信息中包含了一些关键的摘要数据:
- 行数:表中大致有多少行。
- 不同值的个数:某列有多少个不同的值。
- 数据分布直方图:描述数据在各个值上的分布情况。
升级带来的影响:
- 数据迁移与变化:升级过程(特别是跨大版本升级,如Oracle 11g到19c,或SQL Server 2008到2019)通常涉及数据导出、导入或重组,即使逻辑相同,物理存储、行的物理顺序、甚至数据值都可能发生微妙变化,旧统计信息是基于升级前的数据快照,已经过时。
- 直方图兼容性问题:新版本的统计信息可能使用了更先进、更精细的直方图(如频率直方图、Top-N直方图),旧版本的直方图要么不被支持,要么格式不兼容,优化器可能无法正确解析旧直方图,从而回退到最粗略的默认估算(假设数据均匀分布),导致基数(Cardinality)估算偏差巨大。
后果:基数估算偏差会让优化器选择错误的执行计划,一个本应返回几行的查询,因估算偏差被误认为返回几百万行,从而选择了全表扫描而不是高效的内层循环嵌套连接。
新的统计信息特性需要新鲜数据
新版本的数据库通常会带来新的统计信息字段或功能,这些新特性必须基于新的数据才能发挥价值。
- 多列统计信息:新版本可能支持创建跨多列的统计信息(如Oracle的扩展统计信息、SQL Server的列统计信息),能更准确地估算多列联合谓词的选择性,升级后,优化器会尝试使用这些新特性,但如果没有新鲜的、包含列间相关性的统计信息,它就无法工作。
- 分区统计信息:对于分区表,新版本可能支持更细粒度的分区级统计信息(如全局/分区/子分区),升级后,优化器可能会期望使用这些更精确的信息,但旧统计信息可能只有表级别。
- 系统视图与动态管理视图的变化:数据库内部的系统表结构可能变化,导致旧的统计信息被存储为新版系统表的错误位置,或者某些字段被废弃。
避免“扩展执行计划”问题
未更新的统计信息可能导致数据库试图重用来自旧版本SQL语句的执行计划,这种“计划缓存”(Plan Cache)中的旧计划,是为旧版本优化器、旧数据分布设计的,如果统计信息不更新,查询优化器极有可能错误地认为这个旧计划依然是最优的,从而直接重用它,而不是重新生成一个新计划,这被称为计划老化(Plan Staleness),结果就是,系统一直在执行一个低效的计划,性能变差。
具体该怎么做?
数据库版本升级后,强烈建议执行以下操作:
- 立即执行:升级完成后,第一时间对所有用户表的索引和统计信息执行全量更新,可以使用以下命令(示例):
- SQL Server:
EXEC sp_updatestats;或UPDATE STATISTICS [表名] WITH FULLSCAN; - Oracle:
EXEC DBMS_STATS.GATHER_DATABASE_STATS(estimate_percent => 100, cascade => TRUE); - MySQL / PostgreSQL:
ANALYZE TABLE [表名];或ANALYZE;
- SQL Server:
- 使用默认采样:如果表非常大,使用
FULLSCAN可能耗时较长,可以先使用数据库默认的采样率(如SAMPLE 30 PERCENT)快速更新一次,后续在业务低峰期再用FULLSCAN或高采样率重新更新。 - 关注关键索引:除了表统计信息,还要确保所有索引的统计信息也被更新。
- 验证性能:更新后,观察几天内慢查询日志,如果发现某个查询依然性能差,则针对该表和查询涉及的关键列,创建更精细的统计信息(如SQL Server的筛选统计信息、Oracle的扩展统计信息)。
一句话总结:数据库版本升级了它的“大脑”(优化器),你就必须给它一副“新眼镜”(更新的统计信息),否则它看不到最新的数据分布,会走错路。