磁盘排序不是io瓶颈根源,而是内存配置或sql执行路径不当的表象;应优先压降sorts(disk),通过v$sysstat和awr验证是否真由排序引起,并结合sql执行计划定位索引缺失或函数谓词问题。
直接结论:磁盘排序不是io瓶颈的根源,而是内存配置或sql执行路径不当的表象;优先压降 sorts (disk),而非调优存储。
怎么确认是磁盘排序真在拖慢IO
别只看 db file sequential read 高就去动存储。先验证是否真由排序引起:
- 查
V$SYSSTAT:只要sorts (disk)值非零,且占比 >5%(sorts (disk) / (sorts (memory) + sorts (disk))),就说明存在实质性磁盘排序压力 - 结合 AWR 看趋势:执行
DBA_HIST_SYSSTAT查询最近 2 小时内sorts (disk)增量是否突增(单小时超 1000 次基本可定位为某类 SQL 触发) - 注意干扰项:
direct path write temp等待高 ≠ 一定是排序——也可能是哈希连接溢出、UNION ALL 物化或并行中间结果写入,需下钻到SQL Statistics中按Physical Reads和Temp Space双维度排序
为什么19c里磁盘排序更容易爆发
Oracle 19c 的优化器更激进地选择内存外操作,尤其在 PGA 不足或统计信息不准时:
-
_pga_aggregate_target默认值未随物理内存同比例增长,导致PGA_AGGREGATE_TARGET实际偏低,小幅度负载上升就触发 spill - 复杂视图 +
UNION ALL场景下,19c CBO 更倾向物化中间结果到临时表空间,而非重用已有缓冲区 -
workarea_size_policy = AUTO时,单个 SQL 分配的 workarea 可能被低估,尤其当并行度(DEGREE)设得过高但实际数据倾斜严重时 - 隐式转换(如
WHERE to_char(date_col) = '2026-06')导致无法使用索引,全表扫描后叠加ORDER BY+LIMIT,强制走磁盘排序
实操上怎么快速压降磁盘排序
分三步动手,不碰存储、不改硬件也能见效:
- 会话级紧急抑制:对已知问题 SQL 执行
ALTER SESSION SET "_sort_elimination_cost_ratio" = 10000;(阻止优化器选错排序路径)+ALTER SESSION SET WORKAREA_SIZE_POLICY = MANUAL; SORT_AREA_SIZE = 209715200;(临时给足 200MB 内存) - 定位并重写高危 SQL:在 AWR 中找
SQL ordered by Temp Space,重点检查含ORDER BY、GROUP BY、ROW_NUMBER()且Physical Reads Per Execution > 5000的语句;避免在谓词中对列做函数运算 - 调整全局参数但不盲目加 PGA:先查
V$PGASTAT中cache hit percentage是否低于 90%,再按公式PGA_AGGREGATE_TARGET ≈ 20% × SGA_TARGET微调(OLTP 环境不建议超过 40%);禁用_enable_automatic_sql_tuning防止自动任务生成低效执行计划
临时表空间本身要不要优化
要,但仅限于“隔离”和“匹配”,不是“提速”:
- 不要把
TEMP表空间放在和业务数据文件相同的 LUN 或 ASM diskgroup 上——direct path write temp和db file parallel read会争抢 I/O 队列 - SSD 环境下,为 TEMP 单独建一个 ASM diskgroup,
ATTRIBUTE 'au_size'='4M'+'compatible.asm'='19.0',避免 stripe size 过小导致小 IO 放大 - 禁止在 TEMP 表空间启用
ENCRYPTION或COMPRESS——临时段写入本就不该走这些路径,反而增加 CPU 开销 - 迁移后必须压测:用
SELECT /*+ ORDERED USE_NL(t1,t2) */ * FROM big_table t1, small_table t2 WHERE ... ORDER BY t1.id;模拟真实排序负载,观察direct path write temp等待是否下降 30% 以上
最易被忽略的一点:sorts (disk) 高往往意味着执行计划里藏着没走索引的 ORDER BY,而不是 PGA 不够。先查 DBA_HIST_SQL_PLAN 中对应 SQL 的 operation 是否含 SORT ORDER BY 且 options 是 STOPKEY 或空,再决定调内存还是改 SQL。











