最直接表现是LAST_ANALYZED字段为空;新建表、分区或索引未显式收集统计信息时即缺失,需查dba_tab_statistics中last_analyzed IS NULL的记录,并排除系统用户及非段对象。

查 DBA_TAB_STATISTICS 中 LAST_ANALYZED 为 NULL 的表
缺少统计信息最直接的表现就是 LAST_ANALYZED 字段为空。Oracle 不会自动为新创建的表、分区或索引生成统计信息(除非启用了 CREATE TABLE ... STATISTICS 或设置了 OPTIMIZER_DYNAMIC_SAMPLING 级别足够高),所以新建对象后未显式收集,就会落在这个缺口里。
执行前先刷新监控信息,避免缓存延迟误导判断:
EXEC DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO;
然后查空值:
SELECT owner, table_name, partition_name, object_type
FROM dba_tab_statistics
WHERE last_analyzed IS NULL
AND owner NOT IN ('SYS', 'SYSTEM', 'XDB', 'ORDSYS')
AND object_type IN ('TABLE', 'PARTITION', 'SUBPARTITION');
-
owner NOT IN排除系统用户,避免干扰真实业务对象 - 必须加
object_type过滤,否则会混入索引、簇等非段对象(dba_tab_statistics实际涵盖所有“可统计对象”,不单指表) - 注意:视图、物化视图日志等伪段对象也可能返回 NULL,需结合业务上下文人工甄别
用 DBA_OBJECTS + OBJECT_TYPE 过滤未分析的段对象
DBA_TAB_STATISTICS 只包含已有统计信息记录的对象(哪怕 LAST_ANALYZED 是 NULL)。真正完全没进过统计信息字典的对象,在该视图里根本不会出现 —— 这时候就得回退到 DBA_OBJECTS,靠对象类型和状态反推。
关键逻辑:段对象(table/index/partition)若从未被分析过,且不是临时表或 IOT 溢出段,大概率缺失统计信息:
SELECT owner, object_name, object_type, created
FROM dba_objects
WHERE object_type IN ('TABLE', 'INDEX', 'PARTITION', 'SUBPARTITION')
AND owner NOT IN ('SYS','SYSTEM')
AND status = 'VALID'
AND object_name NOT IN (
SELECT table_name FROM dba_tab_statistics
WHERE owner = dba_objects.owner AND table_name = dba_objects.object_name
);
- 这个查询能捕获
DBA_TAB_STATISTICS里完全不存在的记录,比如刚CREATE TABLE就被应用访问的表 - 注意
OBJECT_NAME在分区对象中实际是分区名,需结合OBJECT_TYPE和父对象名(如DBA_PART_TABLES)才能准确定位所属表 - 某些
OBJECT_TYPE = 'TABLE'其实是 IOT 的溢出段(OVERFLOW),它们的统计信息通常随主表一起收集,不必单独处理
检查分区表的子对象是否遗漏统计信息
分区表最容易“局部缺失”:整表有统计信息,但个别分区或子分区没更新。这时候 DBA_TAB_STATISTICS 里会出现同一 TABLE_NAME 多行记录,其中部分 PARTITION_NAME 对应的 LAST_ANALYZED 为 NULL 或远早于其他分区。
重点查这类“孤儿分区”:
SELECT owner, table_name, partition_name, last_analyzed, stale_stats
FROM dba_tab_statistics
WHERE table_name IN (
SELECT table_name FROM dba_part_tables
WHERE owner NOT IN ('SYS','SYSTEM')
)
AND (last_analyzed IS NULL OR stale_stats = 'YES')
ORDER BY owner, table_name, last_analyzed;
- 必须结合
DBA_PART_TABLES筛出真正的分区表,否则普通表的PARTITION_NAME为 NULL,会误报 -
stale_stats = 'YES'表示该分区数据变动超 10%,虽有旧统计信息但已不可信,也属于“事实缺失”范畴 - 如果
granularity设置为'GLOBAL'或'GLOBAL AND PARTITION',可能掩盖子分区缺失问题,需确认收集策略
为什么 DBA_TAB_STATISTICS 有时查不到缺失对象?
核心原因有两个:字典延迟刷新、对象类型覆盖不全。
DBA_TAB_STATISTICS 的内容依赖内存监控数据落盘,而 Oracle 默认不会实时写入 —— 所以刚建完表立刻查,可能还看不到记录;另外,它不包含 LOB 段、IOT 溢出段、嵌套表存储表等隐式段对象,这些对象的统计信息存于 DBA_LOBS、DBA_NESTED_TABLES 等独立视图。
- 执行
DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO后仍查不到,说明该对象尚未触发任何 DML,监控器根本没跟踪它 - LOB 列对应的物理段需单独查:
SELECT owner, table_name, column_name FROM dba_lobs WHERE segment_name IS NOT NULL AND (owner, segment_name) NOT IN (SELECT owner, table_name FROM dba_tab_statistics) - 对
DBA_TAB_STATISTICS的信任不能替代对对象生命周期的理解:它反映的是“统计信息是否登记”,不是“对象是否存在统计信息需求”


















