必须立刻手动收集统计信息,且不能只靠 cascade => TRUE——新分区的 NUM_ROWS 为 0 是常态;因 SPLIT 是纯 DDL 不更新统计,DBMS_STATS.GATHER_TABLE_STATS 默认跳过空分区,需显式指定 granularity => 'ALL' 才能覆盖所有分区。
必须立刻手动收集统计信息,且不能只靠 cascade => true —— 新分区的 num_rows 为 0 是常态,不是异常。
为什么 SPLIT 或新增分区后 NUM_ROWS 还是 0
Oracle 的 ALTER TABLE ... SPLIT PARTITION 是纯 DDL 操作,不触发任何统计信息更新;哪怕你刚往新分区插了百万行,DBA_TAB_PARTITIONS.NUM_ROWS 仍显示 0。这不是 bug,是设计行为——它只改元数据,不碰统计视图。更隐蔽的是:DBMS_STATS.GATHER_TABLE_STATS 默认跳过空分区(哪怕你刚 split 出来、还没 insert,它也认为“该分区无数据”),而用户常误以为 cascade => TRUE 就能覆盖全部。
- 检查方式:运行
SELECT partition_name, num_rows, last_analyzed FROM dba_tab_partitions WHERE table_name = 'YOUR_TABLE' AND table_owner = 'YOUR_SCHEMA',若新分区的num_rows为 0 或last_analyzed时间早于 split 时间,说明没收集到 - 根本原因:默认
granularity是AUTO或TABLE,不会强制扫描所有分区,尤其对刚创建的空分区 - 影响范围:不仅表分区,本地索引分区(
DBA_IND_PARTITIONS)的统计也会滞后,导致索引选择率误判
必须用 granularity => 'ALL' 显式覆盖所有分区
只设 cascade => TRUE 不够,它只控制是否收集索引统计,不决定是否扫新分区。真正起作用的是 granularity 参数:
-
granularity => 'ALL':强制扫描表 + 所有分区 + 所有子分区(含刚 split 出的、空的、未插入的) -
estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE:避免采样偏差,尤其对数据倾斜严重的分区 -
method_opt => 'FOR ALL COLUMNS SIZE AUTO':让直方图按需生成,防止谓词如status = 'PROCESSED'被低估选择率 -
no_invalidate => FALSE:确保依赖该表的游标失效,否则旧执行计划还在缓存里跑
完整调用示例:
EXEC DBMS_STATS.GATHER_TABLE_STATS( ownname => 'SCHEMA_NAME', tabname => 'TABLE_NAME', granularity => 'ALL', estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE, method_opt => 'FOR ALL COLUMNS SIZE AUTO', cascade => TRUE, no_invalidate => FALSE );
查询没走分区裁剪?先确认统计信息真生效了
即使执行了上面的收集,如果执行计划里 PARTITION START/STOP 显示 ALL 或 KEY,大概率还是统计不准或分区键被函数干扰。但别急着改 SQL —— 先验证统计是否落地:
- 查
DBA_TAB_PARTITIONS和DBA_IND_PARTITIONS,不是只看DBA_TAB_STATISTICS.NUM_ROWS(那是汇总值,不影响裁剪) - 若某分区
NUM_ROWS仍是 0,说明granularity => 'ALL'没生效,可能是权限不足(需ANALYZE ANY或对象级权限),或表被锁住 - 遇到
Stattype_Locked = 'ALL':先执行DBMS_STATS.UNLOCK_TABLE_STATS(ownname => 'SCHEMA_NAME', tabname => 'TABLE_NAME')再重收 - 业务高峰期禁止收集:AWR 报告显示,一次全分区统计收集可能引发大量逻辑读争抢,导致会话阻塞
物化视图或本地索引上的统计也得单独刷
物化视图默认不继承基表分区结构,它的统计信息是独立的;本地索引虽与表同分区,但索引统计不会随表统计自动更新。这两类对象的统计滞后,会导致优化器在 JOIN 或回表时严重误判数据量:
- 物化视图:必须显式执行
DBMS_STATS.GATHER_MVIEW_STATS(mview_name => 'MV_NAME'),不能复用基表命令 - 本地索引:即使
cascade => TRUE,也建议单独检查DBA_IND_PARTITIONS.NUM_ROWS,必要时加force => TRUE强制刷新 - 增量统计(12c+)可缓解大表压力,但首次启用仍需全量收集一次,否则增量无效
最易被忽略的一点:granularity => 'ALL' 对物化视图和索引不适用,它们没有这个参数;必须用对应对象的专用收集过程,且路径不能错。











