AWR报告无法直接显示索引使用次数,需通过Segments by Logical/Physical Reads(筛选OBJECT_TYPE='INDEX')定位高热度索引,并结合执行计划、基表读数对比及DBA_HIST_SEG_STAT下钻验证是否低效使用。
awr 报告里没有“索引被用了多少次”的直接计数,sql ordered by reads 本身也不按索引分组——它只列 sql,不告诉你这条 sql 用的是哪个索引。想定位高热度索引,必须跳过这个页面,转向 segments by logical reads 和 segments by physical reads,再反向关联 sql。
为什么不能只看 SQL ordered by Reads
SQL ordered by Reads 统计的是该 SQL 所有逻辑读(含表、索引、LOB、临时段)的总和,无法拆解到具体对象。一条走 INDEX RANGE SCAN + TABLE ACCESS BY INDEX ROWID 的语句,其逻辑读会同时计入索引段和表段,但报告里只归在 SQL 行上,不体现归属。
- 常见错误现象:看到某条 SQL 排第一,就去优化它,结果发现它本就走了高效索引,真正拖慢系统的是另一条没上榜、但反复扫描同一低效索引的 SQL
- Oracle 11g 中,
SQL ordered by Reads的Buffer Gets字段是估算值(尤其带并行或绑定变量时),和实际段级逻辑读常差 2–5 倍 - 该页面默认只显示 top 30,且按 SQL 文本哈希聚合,相同逻辑不同字面量(如硬编码 vs 绑定变量)会被拆成多行,掩盖真实热点
正确路径:从 Segments by Logical Reads 反查索引
打开 AWR 报告后,搜索 Segments by Logical Reads,聚焦 OBJECT_TYPE = 'INDEX' 的行。这才是索引真实被访问强度的代理指标。
- 优先过滤
Owner列为业务 Schema(如SCOTT、HR),排除SYS、SYSTEM下的系统索引干扰 - 看
Logical Reads绝对值,而非 %Total:一个索引读 500 万块,即使只占 DB 总逻辑读 0.3%,也远比读 50 万块但占 5% 的索引更值得查 - 对比同一索引在相邻快照中的读数:若从 200 万 → 800 万,且无应用发布,大概率是执行计划退化或统计信息失效
- 用
Object Name去DBA_OBJECTS查OBJECT_ID,再关联DBA_HIST_SEG_STAT看小时级波动,避开快照间隔不均导致的误判
如何确认是“高热度”还是“低效使用”
逻辑读高 ≠ 索引用得好。得交叉验证三件事:
- 查该索引对应基表的
Logical Reads:若索引读 > 表读 × 1.5,且没大量排序/位图操作,说明回表严重,可能需要覆盖索引 - 进
SQL ordered by Gets页面,用 Ctrl+F 搜该索引名(如ORDERS_IDX_STATUS):如果搜不到任何 SQL,说明这些逻辑读来自全表扫描(即索引存在但未被使用) - 运行
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_AWR('sql_id', NULL, NULL, 'ADVANCED')),检查历史执行计划中是否真出现INDEX RANGE SCAN或INDEX UNIQUE SCAN,而非INDEX FAST FULL SCAN(后者等价于扫索引堆,物理读高但效率低)
Oracle 11g 特别注意点
11g 缺少 12c+ 的实时 SQL 监控和自动索引建议,Segments by Logical Reads 是唯一能批量感知索引访问强度的入口。但它的数据来源是 DBA_HIST_SEG_STAT,而该视图在 11g 中默认只保留 8 天(由 DBA_HIST_WR_CONTROL.retention 控制),过期即不可查。
- 不要依赖单次 AWR 报告下钻:必须先用
dba_hist_snapshot确认目标时段快照存在,再生成报告 - 11g 不支持
ONLINE REBUILD对主键约束索引(constraint_type = 'P'),重建前务必查DBA_CONSTRAINTS,否则会锁表 - 函数索引(如
UPPER(name))在 AWR 中可能归类为FUNCTION-BASED INDEX,但Segments by Logical Reads仍显示为INDEX类型,需结合DBA_INDEXES.function_based字段二次确认











