分区索引维护后性能剧降,大概率是统计信息未更新、分区裁剪失效或本地索引段状态异常;需优先检查DBMS_STATS.GATHER_TABLE_STATS是否指定granularity=>'ALL'、dba_ind_partitions.status是否为UNUSABLE、执行计划中PARTITION_START/STOP是否为ALL而非KEY或具体分区名。
分区索引在维护窗口后性能剧降,大概率不是索引坏了,而是统计信息没更新、分区裁剪失效或本地索引段状态异常——修复动作必须聚焦在这三处,而不是直接重建索引。
分区操作(如 DROP PARTITION、SPLIT PARTITION)本身不改数据分布,但会重置元数据状态。常见诱因包括:
GRANULARITY => 'ALL',导致新分区或索引分区的统计信息为空或陈旧,优化器误判选择性,放弃分区裁剪ADD PARTITION 后),dba_ind_partitions.status 显示 UNUSABLE,但 dba_indexes.status 仍为 VALID,执行计划里出现 INDEX FULL SCAN 而非 INDEX RANGE SCAN PARTITION
UPDATE GLOBAL INDEXES,但某个全局索引因空间不足失败并回滚,残留 UNUSABLE 状态未被清理,后续查询绕过该索引走全表扫描别只看是否走了索引,重点确认是否“按分区走”。执行 EXPLAIN PLAN FOR 后查 PLAN_TABLE:
PARTITION_START 和 PARTITION_STOP 列值是 KEY 或具体分区名(如 P202406),说明裁剪生效ALL,就是全分区扫描——此时即使有索引也白搭,得回头检查 SQL 过滤条件是否含分区键、是否对分区键用了函数(如 TRUNC(dt))或绑定变量未触发 ACSINDEX RANGE SCAN PARTITION;若仍是 INDEX RANGE SCAN(无 PARTITION 后缀),说明优化器没识别到分区边界,大概率是统计信息缺失先确认问题出在“不可用”还是“不可见”:
SELECT partition_name, status FROM dba_ind_partitions WHERE index_name = 'IDX_ORDERS_DT';,若有 UNUSABLE,需重建对应分区:ALTER INDEX IDX_ORDERS_DT REBUILD PARTITION P202406;
SELECT index_name, status FROM dba_indexes WHERE table_name = 'ORDERS';,若为 UNUSABLE,不能只 rebuild,得先确认是否因上次 DDL 中断残留——用 SELECT operation, status FROM dba_objects WHERE object_name = 'IDX_ORDERS_CUSTID'; 辅助判断dba_mview_logs 或 audit_trail 表膨胀也可能拖慢解析,需一并检查Oracle 11g 对分区表的统计收集默认不递归到子对象,DBMS_STATS.GATHER_TABLE_STATS 不加参数等于只扫了表头:
DBMS_STATS.GATHER_TABLE_STATS(ownname => 'SCOTT', tabname => 'ORDERS', granularity => 'ALL');
granularity => 'PARTITION' + partname => 'P202406',避免全量收集耗时ANALYZE TABLE ... COMPUTE STATISTICS,它不支持分区级统计,且 11g 中已被标记为过时维护窗口后的性能抖动,往往卡在统计信息这一步——它不报错、不告警,只默默让优化器选错路。只要分区键过滤条件写法没问题,90% 的“索引失效”都能靠这一条命令拉回来。