分区索引碎片是否需重建,应依据DEL_LF_ROWS/LF_ROWS>0.2、HEIGHT>=4或INDEX FAST FULL SCAN逻辑读异常高来判断,而非仅看空块;重建后须执行SHRINK SPACE COMPACT才能释放空间。
分区表的空间碎片不等于“必须马上处理”,尤其当查询走分区裁剪时,空块可能根本不会被读到。真正需要干预的信号是:逻辑读异常升高、del_lf_rows/lf_rows > 0.2、索引height >= 4,或表级used_rate 且高水位线(hwm)长期未下降。
怎么查分区表的真实碎片率(别信单一看似“空”的块数)
只看DBA_TAB_PARTITIONS.BLOCKS和NUM_ROWS * AVG_ROW_LEN比值容易误判——因为分区可能刚删完数据但统计信息没更新,或PCTFREE预留过大。必须先确保统计信息新鲜:
- 检查是否过期:
SELECT last_analyzed, stale_stats FROM dba_tab_statistics WHERE owner = 'SCHEMA' AND table_name = 'ABC' - 强制刷新(避免锁表):
EXEC DBMS_STATS.GATHER_TABLE_STATS('SCHEMA', 'ABC', CASCADE => TRUE, estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE) - 再算真实使用率:
ROUND((NUM_ROWS * AVG_ROW_LEN) / (BLOCKS * 8192), 3) AS USED_RATE,低于 0.3 才值得继续看
分区索引碎片要不要重建?看这三个指标,不是看“空块”
局部索引的碎片影响远小于全局索引,别一看到leaf_blocks里有空块就跑REBUILD PARTITION。关键看:
-
DEL_LF_ROWS / LF_ROWS > 0.2:说明叶块中 20% 以上行已被删除,后续插入易引发分裂 -
HEIGHT >= 4:B树层级过深,每次索引查找多读 1–2 个块 - 执行
INDEX FAST FULL SCAN时逻辑读远高于同量级健康索引(可用V$SQL查BUFFER_GETS对比) - 注意:
ANALYZE INDEX ... VALIDATE STRUCTURE会锁表,生产环境禁用;改用DBMS_STATS.GATHER_INDEX_STATS
在线整理分区表空间:SHRINK SPACE COMPACT 是首选
对 10 亿级分区表 ABC,MOVE耗时长、需额外维护索引,DBMS_REDEFINITION复杂度高。直接用SHRINK SPACE更稳:
- 必须先开行移动:
ALTER TABLE abc ENABLE ROW MOVEMENT - 只收缩不释放空间(低风险):
ALTER TABLE abc MODIFY PARTITION p2024q1 SHRINK SPACE COMPACT - 要真正释放空间并下移 HWM:
ALTER TABLE abc MODIFY PARTITION p2024q1 SHRINK SPACE CASCADE,但会短暂持表级 X 锁 - 每个分区单独执行、单独 commit,避免一个失败拖垮整批
- 重建后若想释放物理空间,局部索引需补
SHRINK SPACE COMPACT,否则空块仍占段空间
为什么监控和整理常失效?两个隐形坑
很多 DBA 跑完SHRINK发现空间没少、性能没升,问题往往出在:
- 没关自动扩展(
AUTOEXTEND ON):文件已满但表空间还在往里撑,SHRINK释放的空间立刻被新分配吃掉 - 忘了清理
RECYCLEBIN:删过的分区对象还在回收站占着空间,SHOW RECYCLEBIN+PURGE RECYCLEBIN必做


















