AWR报告中大量TABLE ACCESS FULL通常表明索引缺失或设计不当,而非表过大;应优先分析SQL ordered by Elapsed Time,结合DBMS_XPLAN.DISPLAY_AWR和PLAN_HASH_VALUE定位执行计划退化,并依据选择性(
查AWR报告时发现大量TABLE ACCESS FULL,说明什么
这通常不是“表太大所以必须全扫”,而是执行计划没走索引,或者索引根本没建对。oracle在统计信息准确、谓词可sargable的前提下,仍选全表扫描,大概率是现有索引无法支撑查询条件——比如where status = 'a' and create_time > sysdate-7,但只在status上建了单列索引,create_time没包含进去,优化器就很难用上。
从AWR里抓关键SQL,别只看逻辑读Top SQL
AWR的SQL ordered by Gets或SQL ordered by Executions容易误导:高逻辑读未必慢,高执行频次的简单语句也可能挤占榜单。更有效的路径是:
- 先看
SQL ordered by Elapsed Time,挑出平均单次耗时高、且Executions不为0的SQL - 用
DBMS_XPLAN.DISPLAY_AWR查它的历史执行计划,确认是否真有TABLE ACCESS FULL步骤 - 结合
PLAN_HASH_VALUE比对不同时间点的计划变化,排除因绑定变量窥探或统计信息过期导致的临时退化
建复合索引前,先验证字段选择性和过滤基数
不是所有WHERE字段都适合进索引,尤其当某列低选择性(如gender CHAR(1)只有'M'/'F')时,加进复合索引反而拖慢DML和增加维护开销。实操建议:
- 用
SELECT COUNT(DISTINCT col)/COUNT(*) FROM table粗估选择性,低于5%慎入索引 - 对日期范围查询,把高选择性列放前面(如
order_id),时间范围列放后面(如create_time),避免索引跳扫失效 - 如果查询含
ORDER BY create_time DESC,且常配合LIMIT(如ROWNUMcreate_time放在复合索引末尾可避免排序
索引建完不生效?检查三个隐藏开关
即使索引结构合理,也可能被优化器忽略。重点排查:
-
ALTER SESSION SET OPTIMIZER_USE_INVISIBLE_INDEXES = TRUE是否误开启——隐形索引默认不参与计划生成 - 目标列是否用了函数或表达式,比如
WHERE UPPER(name) = 'ABC',需建函数索引CREATE INDEX idx_name_up ON t (UPPER(name)) - 统计信息是否陈旧:
SELECT last_analyzed FROM dba_tables WHERE table_name = 'YOUR_TABLE',若超过3天未更新,跑DBMS_STATS.GATHER_TABLE_STATS再验证
真正卡住性能的,往往不是缺索引,而是索引和查询模式错位——比如按tenant_id, status, create_time建了索引,但应用实际发来的是WHERE create_time > ? AND tenant_id = ?,字段顺序不匹配,索引就只能用上最左前缀tenant_id,后面两个字段失效。这种细节,AWR不会直接告诉你,得对着执行计划一行行对。











