“全表扫描多”需交叉验证三处:SQL ordered by Physical Reads(关注Physical Reads>10万且Executions低)、Top Segments by Physical Reads(定位热点表)、SQL ordered by Executions中对应语句的执行计划(确认是否真实全表扫描),单看任一页面易误判。

怎么看“全表扫描多”不是靠感觉,而是看三个地方
AWR报告里没有“全表扫描次数”这个直接指标,所谓“全表扫描多”必须交叉验证三处数据:SQL ordered by Physical Reads、Top Segments by Physical Reads、以及SQL ordered by Executions中对应语句的执行计划。只盯一个页面容易误判——比如某条SQL执行100次但每次只扫100行,和另一条执行5次却扫千万行,物理读总量可能差不多,但问题根源完全不同。
-
SQL ordered by Physical Reads页面列出物理读最高的SQL,优先关注Physical Reads> 100,000 且Executions较低(比如 -
Top Segments by Physical Reads页面中,如果某张表(OBJECT_NAME列)排进前5,且其PHYSICAL_READS远高于同库其他段,就说明有SQL在反复扫它;再反查该表名是否出现在上一页的高物理读SQL里 -
SQL ordered by Executions页面里,如果某SQL执行频次突增(比如比上周同期+300%),且它关联的表恰好也在Top Segments里,基本可锁定为“本不该高频扫描却正在高频扫描”的异常行为
怎么确认某条SQL真走了全表扫描
AWR报告本身不展示执行计划,必须下钻查历史计划。不能只信当前v$sql里的PLAN_HASH_VALUE,因为共享池里可能已老化出旧计划,而问题发生在快照周期内。
- 从报告中复制目标
sql_id,用DBMS_XPLAN.DISPLAY_AWR查该SQL在指定快照区间的实际计划:SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_AWR('abc123xyz', NULL, NULL, 'ADVANCED')); - 重点搜
FULL TABLE SCAN或TABLE ACCESS FULL字样;若看到INDEX RANGE SCAN但Rows列极小(如1)、Bytes列极大(如数MB),可能是索引选择性崩坏导致优化器弃用,也算隐性全表扫描 - 对比多个快照中的
PLAN_HASH_VALUE是否突变——值变为0或全新数字,常代表执行路径退化,不是SQL写法问题,而是统计信息/数据分布变化引发
为什么加了索引还是走全表扫描
常见误区是“建了索引就万事大吉”,但AWR里反复出现的全表扫描,往往卡在三个被忽略的环节:
-
NUM_ROWS统计信息过期:比如表刚INSERT了200万行,但LAST_ANALYZED还是三个月前,优化器按老数据估算成本,认为走索引更贵 -
CLUSTERING_FACTOR严重恶化:数据按时间插入但索引字段是随机ID,导致索引叶块指向的表块极度离散,一次索引扫描要读几十个不同数据块,成本反超全表扫描 - 隐式类型转换:SQL里写
WHERE order_id = '123'而order_id是NUMBER类型,索引失效;这种SQL在SQL ordered by Parse Calls里常伴随高硬解析,但报告里不直接标出
别急着重建索引,先看它是不是被约束强依赖
ALTER INDEX ... REBUILD在线业务中风险极高,尤其当索引背后挂着主键或唯一约束时——Oracle会触发全表验证,阻塞DML,还可能因空间不足失败。
- 务必先查:
SELECT constraint_name, constraint_type FROM dba_constraints WHERE index_name = 'YOUR_IDX_NAME';
若返回P(Primary Key)或U(Unique),就不能直接REBUILD - 对PK索引,Oracle 12c之前不支持
ONLINE选项;12c+虽支持,但需额外检查ENABLED状态和DEFERRABLE属性 - 真正该重建的,是那些在
Top Segments by Physical Reads里长期高IO、且对应SQL执行计划持续FULL、但dba_indexes里STATUS为VALID的索引——说明结构失衡,而非损坏
全表扫描本身不是病,高频+高单次扫描量+无业务必要性才是病根;AWR只是线索集,最终得回到SQL文本、数据分布、应用逻辑三层去闭环验证,否则优化动作容易打偏。











