AWR报告不记录索引使用频次,需结合dba_hist_seg_stat(过滤INDEX、排除系统对象、窄时间窗口)与ASH下钻执行计划才能准确判断索引是否高效使用。
awr报告本身不记录索引被用了多少次,只提供段级聚合数据;要判断索引是否真被高效使用,必须交叉比对segments by logical reads、segments by physical reads和segments by buffer busy waits,再下钻到dba_hist_seg_stat过滤object_type = 'index',否则全是干扰项。
直接翻AWR报告里的Segment Statistics表格没用——它默认只列top 5,且不区分对象类型。真正信号藏在基表里:
dba_hist_seg_stat,加条件statistic_name IN ('physical reads', 'logical reads'),别漏掉logical reads
JOIN dba_objects时用dataobj#匹配object_id(分区索引必须这么连,否则查不到子分区)OBJECT_TYPE = 'INDEX'且OWNER NOT IN ('SYS','SYSTEM','XDB'),排除系统对象snap_id BETWEEN 1234 AND 1235,避免跨天聚合把偶发扫描放大成常态一个索引physical reads高,可能是主键等值查询的合理行为;但若它的physical reads远高于对应基表,就危险了:
access_predicates为空?说明SQL谓词根本没走索引(比如WHERE UPPER(name) = 'ABC')clustering_factor:如果接近表行数,说明数据物理分布和索引顺序严重偏离,范围扫描代价飙升physical reads direct高的索引通常不是被扫描,而是被并行DML或大查询直读,这种读不进buffer cache,也不会体现在logical reads里Segments by Logical Reads无法区分“一次高效索引唯一扫描”和“一万次低效范围扫描+回表”,更掩盖不了执行计划变更的影响:
ash.sql_id → dba_hist_sql_plan → plan_table_output,过滤operation含INDEX的行access_predicates和filter_predicates是否匹配SQL谓词,尤其注意函数索引是否被真正命中Buffer Busy Waits高,不一定是索引热块争用——反向键索引在高并发插入时也会触发叶块争用,根源不在查询逻辑最易忽略的是:AWR里看到的索引读数,可能来自全表扫描后的回表操作,而不是索引本身被驱动;没有ASH下钻确认执行计划分支,单看Segment Statistics就是雾里看花。