问题根源是HWM高位滞留导致空块过多,需检查BLOCKS与NUM_ROWS比值;先执行DBMS_STATS.GATHER_TABLE_STATS并指定granularity='PARTITION'或cascade=>true,确保LAST_ANALYZED≤5分钟前。
备份集远大于实际数据量,大概率是hwm卡在高位没下来,不是备份工具的问题,而是表里空块太多。
查BLOCKS和NUM_ROWS比值是否异常
别只看dba_segments.bytes——它反映的是段分配的总空间,和真实数据量无关。真正要盯的是BLOCKS(HWM以下已格式化块数)和NUM_ROWS(行数)的比值。
- 执行前必须先收集统计信息:
DBMS_STATS.GATHER_TABLE_STATS,且显式指定granularity => 'PARTITION'(分区表)或cascade => true(含索引) - 检查
LAST_ANALYZED时间,必须≤5分钟前;否则BLOCKS可能为空或严重过期 - 计算
NUM_ROWS / BLOCKS:若 -
EMPTY_BLOCKS对分区表恒为0,别信它;对非分区表也仅在ANALYZE TABLE ... COMPUTE后才有效,DBMS_STATS不填这个字段
确认HWM是否真拖慢了全扫性能
HWM高≠一定慢,得看实际I/O是否真的读了那么多空块。Oracle有优化机制,比如启用了COMPRESS或INMEMORY时,physical reads可能远低于BLOCKS值。
- 开10046跟踪,跑
SELECT COUNT(*) FROM your_table PARTITION (p2025_q3),看physical reads是否接近BLOCKS - 对比
db file sequential read等待次数:若远高于NUM_ROWS,说明大量单块读落在空块上 - 加
/*+ NO_PARALLEL */再测,排除并行协调块干扰判断
用SHRINK SPACE在线整理前必须做三件事
ALTER TABLE ... SHRINK SPACE看着简单,跳过任一前置条件都会报错或无效。
- 表空间必须是本地管理(
EXTENT MANAGEMENT LOCAL)且启用自动段空间管理(SEGMENT SPACE MANAGEMENT AUTO) - 必须先执行:
ALTER TABLE your_table_name ENABLE ROW MOVEMENT——否则直接报ORA-10636: row movement is not enabled - 建议分两步:
SHRINK SPACE COMPACT(只整理不降HWM,业务影响最小),再SHRINK SPACE(真正释放空间回表空间) - 注意:
SHRINK SPACE会短暂持有SSX锁,DML会被阻塞几秒到几十秒,避开高峰时段
TRUNCATE PARTITION和DELETE的HWM行为完全不同
这是最常被混淆的点:删数据不等于降HWM。
-
DELETE FROM ... WHERE partition_key = ...:只标记行失效,BLOCKS不变,HWM纹丝不动 -
TRUNCATE PARTITION p2025_q3:直接重置该分区HWM为0,BLOCKS归零,不可回滚,但快且干净 -
MOVE PARTITION虽能降HWM,但会失效本地索引、中断长事务,且需要额外空间;SHRINK更轻量,但要求ASSM
碎片不是越碎越要动,而是看physical reads是否真在读空块——没验证就SHRINK或MOVE,只是把问题从存储层转移到维护窗口里。











