在Oracle数据库的日常运维中,统计信息是优化器生成高效执行计划的核心依据,过期的统计信息会导致优化器误判数据分布,进而生成低效的执行计划,引发查询性能问题。因此需要定期检查并识别过期的统计信息,及时完成重新收集。

统计信息过期的判断逻辑
Oracle通过数据字典记录表的统计信息收集时间、数据变更量等信息,判断统计信息是否过期的核心依据是:自上次统计信息收集后,表的数据变更量(增删改操作的总行数)是否超过了阈值。默认情况下,当变更量超过表总记录数的10%时,就会认为该表的统计信息已经过期。
相关核心数据字典视图
判断统计信息是否过期主要依赖DBA_TAB_STATISTICS视图,该视图存储了所有表的统计信息相关属性,核心字段如下:
- OWNER:表所属的用户名
- TABLE_NAME:表名称
- LAST_ANALYZED:上次统计信息收集的时间
- STALE_STATS:统计信息是否过期,取值为YES表示过期,NO表示未过期
- NUM_ROWS:统计信息记录的总行数
查询过期统计信息的SQL示例
执行以下SQL可以直接查询当前数据库中所有过期的统计信息:
-- 查询所有过期的统计信息
SELECT
OWNER,
TABLE_NAME,
LAST_ANALYZED,
NUM_ROWS
FROM
DBA_TAB_STATISTICS
WHERE
STALE_STATS = 'YES'
-- 排除系统用户下的表,可根据实际需求调整
AND OWNER NOT IN ('SYS', 'SYSTEM', 'OUTLN', 'DBSNMP')
ORDER BY
OWNER, TABLE_NAME;针对分区表的特殊处理
如果是分区表,除了查看表级别的统计信息过期状态,还需要检查分区级别的统计信息,对应的视图是DBA_TAB_PARTITIONS,查询逻辑和表级别类似:
-- 查询分区表中过期的分区统计信息
SELECT
TABLE_OWNER,
TABLE_NAME,
PARTITION_NAME,
LAST_ANALYZED,
NUM_ROWS
FROM
DBA_TAB_PARTITIONS
WHERE
STALE_STATS = 'YES'
AND TABLE_OWNER NOT IN ('SYS', 'SYSTEM', 'OUTLN', 'DBSNMP')
ORDER BY
TABLE_OWNER, TABLE_NAME, PARTITION_NAME;手动触发统计信息重新收集
定位到过期的统计信息后,可以使用DBMS_STATS包手动重新收集,示例如下:
-- 重新收集指定表的统计信息
BEGIN
DBMS_STATS.GATHER_TABLE_STATS(
OWNNAME => 'SCOTT', -- 表所属用户
TABNAME => 'EMP', -- 表名称
CASCADE => TRUE -- 同时收集索引的统计信息
);
END;
/如果需要批量重新收集过期的统计信息,也可以使用DBMS_STATS.GATHER_SCHEMA_STATS过程,指定OPTIONS => 'GATHER STALE'参数,会自动收集当前用户下所有过期统计信息的表的统计信息。
Oracle统计信息过期统计信息DBA_TAB_STATISTICS修改时间:2026-05-24 23:50:11