“Segments by Logical Reads”不是碎片指标,因其仅反映访问热度而非空间浪费;真正需关注的是db file sequential read等待及Physical Reads/Logical Reads比值是否异常升高。
awr里“segments by logical reads”本身不能直接识别碎片表,它反映的是访问热度,不是空间浪费程度。 误把高逻辑读的表当碎片表处理,反而可能引发锁、中断业务、浪费维护窗口。
为什么“Segments by Logical Reads”不是碎片指标
这个报告项统计的是某段时间内哪些段被逻辑读最多,本质是“谁被查得最勤”,和“块是否离散”无关。一张小而热的配置表、索引、甚至系统表(如OBJ$)常年排在前列,但它们几乎不可能有碎片。
- 逻辑读高 ≠ 物理读高:碎片的核心特征是
Physical Reads / Logical Reads比值异常升高 - 逻辑读高 ≠ 高水位下空块多:全表扫描慢是因为要扫一堆空块,但逻辑读计数不区分空/满
- 逻辑读高常伴随缓存命中好:说明数据已在 buffer cache,IO压力未必大
真正该盯住的AWR指标:db file sequential read + Physical Reads/Logical Reads
碎片导致的性能退化,最终会落在单块读等待上——因为数据块在磁盘上跳着分布,一次查询要反复寻道。
- 进AWR报告的
Top 5 Timed Events,重点看db file sequential read的Av Rd(ms)是否 >15ms - 翻到
Instance Activity Stats部分,计算:Physical Reads / Logical Reads比值 - 该比值 >0.15(即每100次逻辑读伴随15+次物理读),且相比基线时段翻倍,才值得怀疑IO层碎片
- 必须排除干扰:用
SQL Statistics → SQL ordered by Physical Reads确认高物理读是否集中在几张业务表,而非归档、备份或大范围全扫
定位具体表的SQL:别只看user_extents,要算实际利用率
查user_extents只能看到分配了多少块,看不出里面填了多少数据。必须结合统计信息算真实空间占用率。
- 先确保统计准确:
EXEC DBMS_STATS.GATHER_TABLE_STATS(ownname => 'SCHEMA_NAME', tabname => 'TABLE_NAME') - 执行评估SQL(替换
SCHEMA_NAME和TABLE_NAME):
SELECT
t.table_name,
ROUND((t.avg_row_len * t.num_rows) / (1 - t.pct_free/100) / 8192, 0) actual_blocks,
a.alloc_block,
ROUND(1 - ((t.avg_row_len * t.num_rows) / (1 - t.pct_free/100) / 8192) / a.alloc_block, 2) fragmentation_ratio
FROM user_tables t,
(SELECT segment_name, SUM(blocks) alloc_block FROM user_extents GROUP BY segment_name) a
WHERE t.table_name = a.segment_name
AND t.owner = a.owner
AND t.owner = 'SCHEMA_NAME'
AND t.table_name = 'TABLE_NAME';- 满足两个条件才考虑整理:
fragmentation_ratio > 0.25且alloc_block * 8192 > 104857600(即表大小 >100MB) - 注意LOB字段:若表含LOB列,
SHRINK必须加CASCADE,否则LOB段不收缩
shrink space前最容易漏掉的三件事
直接跑ALTER TABLE ... SHRINK SPACE大概率报错或无效,这几个前置动作缺一不可。
- 确认表空间是ASSM(自动段空间管理):
SELECT SEGMENT_SPACE_MANAGEMENT FROM dba_tablespaces WHERE tablespace_name = 'YOUR_TS',结果必须是AUTO - 开启行移动:
ALTER TABLE table_name ENABLE ROW MOVEMENT(SHRINK COMPACT也需此步) - 避开高峰并预留足够UNDO:
SHRINK SPACE会产生大量UNDO,长时间运行可能触发ORA-01555,建议在低峰执行,且UNDO_RETENTION设为至少3600秒
碎片整理不是“定期体检”,而是当db file sequential read等待突增、Physical Reads / Logical Reads比值恶化、且锁定到具体大表时,才值得动刀。否则,盲目收缩一张10GB的热表,可能比不处理更伤业务。


















