awr报告中通过“top segments by physical reads”定位高i/o索引,结合sql执行计划、统计信息及依赖项检查,确认并重建碎片化索引,最后验证物理结构、统计信息与i/o性能三重指标。
直接看“top segments by physical reads”定位高i/o索引
awr报告本身不直接显示索引碎片率,但segments by physical reads(通常在“instance activity stats”之后的独立章节)能暴露问题索引——那些物理读飙升、且对应表上本应走索引却实际走了全表扫描的段,往往就是碎片严重或已失效的索引载体。
- 重点找
OBJECT_NAME列中带INDEX后缀的行(如ORDERS_IDX_CREATED),同时检查其PHYSICAL_READS是否远高于同表其他索引或历史均值 - 若该索引关联的表在
SQL ordered by Gets或SQL ordered by Physical Reads里反复出现,且执行计划含FULL TABLE SCAN,基本可判定:索引虽存在,但优化器因统计信息陈旧、选择性下降或B树结构失衡而弃用 - 注意排除LOB索引或函数索引——它们在AWR中可能归类为
LOBSEGMENT而非普通INDEX,需结合DBA_SEGMENTS二次确认
用“SQL ordered by Executions”交叉验证全表扫描激增
单看物理读容易误判:可能是大范围查询本就需要扫表。真正危险的信号是相同SQL在短时间内执行次数暴增,且每次都是全表扫描——这说明应用层逻辑没变,但索引突然“不工作”了。
- 打开
SQL ordered by Executions,筛选EXECUTIONS增幅>200%且PARSE_CALLS同步上升的SQL;再查其PLAN_HASH_VALUE是否与历史快照不同(突变为0或全新值,常代表执行计划变更) - 对这类SQL,立刻用
DBMS_XPLAN.DISPLAY_AWR查历史执行计划:SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_AWR('sql_id_here', NULL, NULL, 'ADVANCED'));比对前后是否从INDEX RANGE SCAN退化为TABLE ACCESS FULL - 常见诱因不是索引损坏,而是
NUM_ROWS统计信息过期(尤其LAST_ANALYZED早于最近一次大批量INSERT/DELETE),或CLUSTERING_FACTOR因数据插入顺序恶化导致索引效率归零
重建前必须查清三个依赖项,否则可能锁库或失败
Oracle里ALTER INDEX ... REBUILD不是无感操作,尤其在线业务场景下,一个没看清的约束就能让维护窗口变成事故现场。
- 先跑:
SELECT constraint_name, constraint_type FROM dba_constraints WHERE index_name = 'YOUR_IDX_NAME';
如果返回P(Primary Key)或U(Unique),说明该索引被约束强依赖——REBUILD会触发约束验证,可能阻塞DML,且ONLINE选项在Oracle 12c之前不支持PK索引 - 查
dba_indexes的LOGGING和TABLESPACE属性:若原索引是NOLOGGING,重建时未显式指定NOLOGGING,会导致大量redo生成;若目标表空间剩余空间<索引当前大小×1.3,REBUILD会直接报ORA-01652 - 确认
DBA_INDEXES中STATUS为VALID且DOMIDX_STATUS为空——若为FAILED或UNUSABLE,REBUILD前得先ALTER INDEX ... REBUILD ONLINE(强制在线模式绕过部分锁)
重建后必须对比三组指标,否则等于没做
命令返回PL/SQL procedure successfully completed只是开始。碎片清理效果、执行计划回归、I/O压力变化,三者缺一不可。
- 立刻查物理结构:
SELECT avg_fragmentation_in_percent, avg_page_space_used_in_percent FROM sys.dm_db_index_physical_stats(...);
(SQL Server)或Oracle用ANALYZE INDEX ... VALIDATE STRUCTURE后查INDEX_STATS——重点看DEL_LF_ROWS/LF_ROWS比值是否从>30%降到<5% - 强制刷新统计信息:
EXEC DBMS_STATS.GATHER_INDEX_STATS('SCHEMA','INDEX_NAME',estimate_percent=>100,cascade=>TRUE);否则优化器仍按旧基数计算,可能继续跳过刚重建的索引 - 等15分钟,重跑同一AWR报告区间,对比
Physical Reads Per Sec是否下降、db file sequential read等待事件总时间是否减少>40%——如果这两项没动,大概率是索引设计本身不合理(比如在低基数字段上建B树索引),重建只是掩盖问题
碎片率数字好看,不代表查询变快;执行计划回去了,不代表I/O真降了;最常被跳过的一步,是拿重建前后的AWR里同一SQL的Elapsed Time Per Exec做减法——差值才是你这次操作的真实价值。










