摘要:明明是一个取前200条数据的分页操作,却跑了 1.7秒、9277逻辑读,业务慢到怀疑人生?
明明是一个取前200条数据的分页操作,却跑了 1.7秒、9277逻辑读,业务慢到怀疑人生?
❓ 为什么分页SQL这么慢? ❓ 是不是排序字段选错了? ❓ 创建了索引却没用上?
我们拿真实案例来拆给你看,不仅优化思路清晰,还能直接套用!
01
适用环境
oracle 11g及以上版本
linux 6.9及以上版本
02
分页SQL介绍
下面的示例使用SH模式表。
1. 11G版本的分页SQL
1)ROWNUM 伪列(嵌套子查询)
对应的执行计划
2)ROW_NUMBER 窗口函数
对应的执行计划
2. 12C及以上版本的分页SQL
对应的执行计划
注意
确保在分页查询中使用 ORDER BY 子句,否则返回的结果顺序可能不确定。
OFFSET - FETCH 子句是最简洁的写法,它的本质实际上就是调用了ROW_NUMBER窗口函数,但需要 Oracle 12c 及以上版本支持。
ROWNUM 伪列在处理排序时需要特别注意,通常需要嵌套子查询。
03
SQL案例
接下来,结合示例库SH模式,以一个案例分析分页SQL。
1. SQL文本
2. SQL执行计划
3. SQL资源消耗
该SQL平均执行一次返回200条数据,耗时1.7秒,逻辑读9277。
04
问题分析及优化思路
通过分析SQL文本,典型的分页SQL。
从执行计划来看,ID=4显示SORT ORDER BY,说明数据汇总之后进行的排序,未利用索引排序特性,不是最优的执行计划。另外该SQL也未利用正确的分页框架,会导致扫描表或索引所有的块。
分页SQL通常可以利用索引优化,让执行计划走NL,确保NL的驱动表是排序列的主表。
05
优化方案
1. 索引方案
通过分析SQL,排序列来源于sales表,确认sales表为NL的驱动表。
1)使用正确的分页框架
2)创建索引
3)添加HINT查看执行计划
通过对比,优化前耗时1.7秒,逻辑读9277,优化后0.01秒,逻辑读221。
有兴趣的小伙伴可以测试同一个表多个列排序、不同表多个列排序的场景。
06
优化成果对比
✅ 性能暴涨 178 倍,逻辑读下降 95.7%
写在最后
分页 SQL 的优化,关键在于三点:
索引设计
ORDER BY字段优先 + 过滤条件做前缀列
查询结构简洁
使用正确的分页框架,提前剪枝
执行路径引导
合理添加 HINT,引导执行计划走 NL
📌 建议定期刷新统计信息,保持优化器认知准确。
彩蛋建议|实战推荐练手场景
✅ 同表多列排序分页
✅ 不同表混合条件下的分页
✅ 分页 + 分组 + TOP-N 限制场景
有兴趣的朋友可以留言交流,一起卷起来 !
来源:嚣张科技圈
