分区裁剪是否生效,先看执行计划中是否有partition start/stop字段,若缺失或显示all/key/rowid,则裁剪失败,实际扫描全部分区;常见原因包括分区键上使用函数、隐式类型转换、绑定变量未启用bind-aware、统计信息过期等。
分区裁剪没生效?先看执行计划里有没有 partition start/stop
分区裁剪是否起作用,awr报告本身不直接显示“裁剪率”,必须靠反向验证:查该sql在awr中关联的执行计划。如果dbms_xplan.display_awr输出里压根没出现partition start和partition stop这两行,说明裁剪失败,查询实际扫了全部分区。
常见干扰项包括:WHERE to_char(part_col, 'yyyymmdd') = '20260624'(函数导致无法匹配分区键)、WHERE part_col = :bind_var但未启用bind_aware特性(12c默认开启,但需确认_optimizer_adaptive_plans=TRUE且统计信息新鲜)。
- 检查绑定变量类型是否与分区列一致:比如分区列是
DATE,传入字符串会触发隐式转换,裁剪失效 - 确认统计信息未过期:
SELECT stale_stats FROM dba_tab_statistics WHERE owner = 'SCHEMA' AND table_name = 'T_PART'返回YES就立刻刷新 - 避免在分区键上做任何运算或函数调用——哪怕只是
NVL(part_col, sysdate)也会让优化器放弃裁剪
AWR里怎么定位“假分区表”?看 SQL ordered by Gets 里的 Buffer Gets per Exec
真正有效的分区裁剪会大幅降低逻辑读。如果某条本应只查单个分区的SQL,在SQL ordered by Gets里Buffer Gets per Exec高达几十万甚至百万,基本可断定裁剪没生效,或者分区设计与查询模式错配(比如按CREATE_TIME范围分区,但查询条件却是STATUS字段)。
- 对比正常时段与异常时段:同一SQL在问题时段
Buffer Gets per Exec翻倍,而Rows Processed per Exec不变,大概率是裁剪退化 - 注意
Executions值:若执行次数极少(如1次),Buffer Gets per Exec参考价值低;优先盯Executions > 10且Buffer Gets per Exec > 50000的语句 - 别只信
Partition Count字段:AWR里这个值可能显示“4”,但实际执行时仍扫全部,必须结合执行计划和逻辑读交叉判断
为什么 gv$segment_statistics 比 AWR 更适合查分区访问分布?
AWR报告汇总的是SQL级统计,看不出数据物理分布。要确认某查询是否真的只触达目标分区,得查gv$segment_statistics视图,它记录每个分区段的逻辑读、物理读等真实IO行为。
例如执行:
SELECT owner, object_name, subobject_name, statistic_name, value
FROM gv$segment_statistics
WHERE object_name = 'T_PART'
AND statistic_name IN ('logical reads', 'physical reads')
AND value > 0
ORDER BY value DESC;
-
subobject_name列即分区名,若多个分区logical reads都非零,说明裁剪未生效或存在跨分区JOIN - RAC环境下必须用
gv$而非v$,否则只看到当前节点的访问情况 - 该视图数据是实时累积的,不是快照,查之前先
EXEC DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO确保最新
分区键选择不当导致裁剪失效,AWR里最隐蔽的信号是什么?
不是等待事件飙升,也不是CPU暴涨,而是Instance Efficiency Percentages区域里Buffer Hit Ratio突然掉到60%以下,同时db file sequential read等待时间(Av Rd(ms))并未升高——这说明大量逻辑读来自内存,但缓冲区命中率骤降,典型特征是扫描了远超必要的分区块,把不该进缓存的数据全塞进db_cache_size。
- 这种现象常伴随
SQL ordered by Reads中多条SQL共享同一个大表名,且Reads per Exec差异极大(有的扫1个分区,有的扫全部) - 别急着加内存:先确认分区键是否被查询高频过滤;若90%的SQL都按
STATUS查,却按CREATE_TIME分区,再调优也没用 - 12c的
DBMS_SPACE.SPACE_USAGE可查各分区真实空间使用率,若多数分区USED_BYTES / BLOCKS * 8192
分区裁剪效率不能靠“看起来分了区”来判断,AWR里每一条高逻辑读SQL背后,都得手动核对执行计划和分区访问分布。最容易被忽略的是绑定变量类型不匹配和统计信息陈旧——这两点不解决,其他所有分析都是徒劳。











