Oracle索引碎片率需通过ANALYZE INDEX VALIDATE STRUCTURE后查INDEX_STATS中del_lf_rows/lf_rows×100计算,超20%且height≥4或聚簇因子异常时应重建;重建后须手动收集索引统计信息。

查 DBA_SEGMENTS 和 DBA_INDEXES 联合判断碎片是否严重
Oracle 没有直接叫“索引碎片率”的内置指标,但可通过 blocks(已分配块数)与 num_rows(实际行数)的比值粗略评估。真正关键的是 del_lf_rows / lf_rows * 100 —— 这个来自 INDEX_STATS 的比率才反映逻辑删除比例,超过 20% 就该警惕。
先执行 ANALYZE INDEX ... VALIDATE STRUCTURE(注意:仅对当前会话有效,不走自动统计),再查 INDEX_STATS:
ANALYZE INDEX schema_name.idx_name VALIDATE STRUCTURE;
SELECT name, height, del_lf_rows, lf_rows,
ROUND(del_lf_rows/NULLIF(lf_rows,0)*100, 2) AS del_pct
FROM INDEX_STATS;常见错误:漏掉 VALIDATE STRUCTURE 就查 INDEX_STATS,结果全是上一次分析的残留数据,del_pct 完全不可信。
重建前必须检查索引是否被 NOLOGGING 或并行属性影响
ALTER INDEX ... REBUILD 默认继承原索引属性,如果原索引建在 NOLOGGING 表空间、或带 PCTFREE/PARALLEL,重建后可能意外丢失日志记录能力,或引发 RAC 环境下的 DML 阻塞。
务必先确认原始定义:
SELECT index_name, logging, degree, pct_free, tablespace_name FROM DBA_INDEXES WHERE owner = 'SCHEMA_NAME' AND index_name = 'IDX_NAME';
实操建议:
- 生产环境重建一律显式加
LOGGING,除非你明确需要跳过归档 - 若原
degree > 1,重建时加PARALLEL N,但完成后立刻ALTER INDEX ... NOPARALLEL,避免后续 DML 被隐式并行拖慢 -
PCTFREE值建议保持不变;盲目调高会导致空间浪费,调低则加速新碎片
在线重建用 ONLINE,但要注意唯一索引和主键的限制
ALTER INDEX ... REBUILD ONLINE 允许 DML 并发,但有硬性约束:不能用于函数索引、域索引,且唯一索引重建期间禁止 INSERT 重复键值(会报 ORA-08104)。主键索引重建更需谨慎——若表上有未提交的事务,ONLINE 重建可能卡住。
安全做法:
- 非紧急情况优先选窗口期执行普通重建:
ALTER INDEX idx_name REBUILD - 必须在线时,提前用
SELECT blocking_session FROM V$SESSION WHERE event LIKE 'enq: TX%'排查阻塞源 - 重建后立刻运行
ANALYZE INDEX ... VALIDATE STRUCTURE再查一次del_pct,验证是否真降下来了
REBUILD 后不更新统计信息,执行计划可能继续走坏
重建索引只重排物理结构,DBA_INDEXES.num_rows 和 DBA_TAB_STATISTICS 不会自动刷新。优化器仍按旧统计信息估算成本,很可能继续忽略这个刚修好的索引。
必须补一手:
EXEC DBMS_STATS.GATHER_INDEX_STATS( ownname => 'SCHEMA_NAME', indname => 'IDX_NAME', estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE);
容易踩的坑:
- 误用
GATHER_TABLE_STATS代替GATHER_INDEX_STATS,后者更精准且快得多 - 在 12c+ 中开启
INCREMENTAL统计的表,单独 gather index 可能触发全表扫描,需确认DBA_TAB_STATISTICS.incremental值
碎片不是孤立问题,它常和统计信息陈旧、绑定变量窥探失效、甚至底层存储条带不对齐耦合。单靠 rebuild 很难根治,得盯住 del_pct 和执行计划里索引的实际 access_predicates 是否匹配。


















