新闻详情

新闻详情

首页 / 资讯中心 / 详情

分页语句使用row_number引发的性能问题

发布时间:2026/9/25 19:20:55来源:尧图网络
分页语句使用row_number引发的性能问题
背景今天给客户优化时发现客户在使用了分页语句中使用了row_number而引发了性能问题那客户是怎样使用row_number引发了性能问题在分页语句中如何处理我们来模拟实验下模拟这了减少复杂度我们用单表查询来模拟客户性能问题场景使用row_number获取排序序号order by 中使遥获取的序号rn来排序SELECT o_orderkey, o_custkey, o_orderstatus, row_number() over(ORDER BY o_orderkey) AS rn FROM orders ORDER BY rn LIMIT 10;分析我们通过执行计划来分析EXPLAINANALYZESELECTo_orderkey,o_custkey,o_orderstatus,row_number()over(ORDERBYo_orderkey)ASrnFROMordersORDERBYrnLIMIT10;QUERYPLAN------------------------------------------------------------------------------------------------------------------------------------------------------------Limit(cost944415.29..944415.32rows10width10)(actualtime31868.066..31868.068rows10loops1)-Sort(cost944415.29..963165.29rows7500000width10)(actualtime31868.063..31868.064rows10loops1)SortKey:(row_number()OVER(?))Sort Method:top-N heapsort Memory:25kB-WindowAgg(cost0.00..782342.99rows7500000width10)(actualtime5.350..30514.771rows7500000loops1)-IndexScanusingorders_pkeyonorders(cost0.00..669842.99rows7500000width10)(actualtime4.445..22712.714rows7500000loops1)Total runtime:31880.744ms(7rows)通过执行计划可以看到我们只需要返回10行而耗时30多秒 这是不合理的再细看执行计划发现这是扫描了全表的数据 (见执行计划里 rows7500000)我们只需要前面有效的10行数据能不能不扫描这么多行而现在这个语句又是什么了什么情况呢通过分析现有的PLAN可以看到实际在执行时是分为几步先把所有符合条件的数据都取出生成rn根据rn对结果排序排序好的数据取前10行与下面语句的PLAN是一样的 (因有了缓存下面执行时间会变短)EXPLAINANALYZESELECT*FROM(SELECTo_orderkey,o_custkey,o_orderstatus,row_number()over(ORDERBYo_orderkey)ASrnFROMorders)ORDERBYrnLIMIT10;QUERYPLAN-----------------------------------------------------------------------------------------------------------------------------------------------------------Limit(cost1019415.29..1019415.32rows10width18)(actualtime10535.425..10535.428rows10loops1)-Sort(cost1019415.29..1038165.29rows7500000width18)(actualtime10535.423..10535.424rows10loops1)SortKey:(row_number()OVER(?))Sort Method:top-N heapsort Memory:25kB-WindowAgg(cost0.00..782342.99rows7500000width10)(actualtime0.140..9302.427rows7500000loops1)-IndexScanusingorders_pkeyonorders(cost0.00..669842.99rows7500000width10)(actualtime0.112..5013.849rows7500000loops1)Total runtime:10550.207ms(7rows)优化分页语句的要点有两个1、 通过索引直接返回有序数据避免排序消耗2、 获取到需要的数据后停止扫描减少无用的扫描消耗我们改用常用的方式也就是直接根据原有列而row_number的结果来排序对比下前后效果EXPLAINANALYZESELECTo_orderkey,o_custkey,o_orderstatus,row_number()over(ORDERBYo_orderkey)ASrnFROMordersORDERBYo_orderkeyLIMIT10;QUERYPLAN---------------------------------------------------------------------------------------------------------------------------------------------Limit(cost0.00..1.04rows10width10)(actualtime0.191..0.216rows10loops1)-WindowAgg(cost0.00..782342.99rows7500000width10)(actualtime0.189..0.193rows10loops1)-IndexScanusingorders_pkeyonorders(cost0.00..669842.99rows7500000width10)(actualtime0.162..0.184rows11loops1)Total runtime:0.317ms(4rows)o_orderkey本身就是主键索引原始语句的PLAN中就已经可以看到(Index Scan using orders_pkey)所以这儿就不再展示表结构了改写后可以看到只访问了11行 (rows11) 而原来是 (rows7500000)因为返回的是有序数据所以改写后也少了 sort当然在该语句或类似语句城 row_number 已经没什么意义 我们可以改用 rownum 伪列来产生RNEXPLAINANALYZESELECTo_orderkey,o_custkey,o_orderstatus,rownumASrnFROMordersORDERBYo_orderkeyLIMIT10;QUERYPLAN---------------------------------------------------------------------------------------------------------------------------------------Limit(cost0.00..0.89rows10width10)(actualtime0.040..0.044rows10loops1)-IndexScanusingorders_pkeyonorders(cost0.00..669842.99rows7500000width10)(actualtime0.040..0.043rows10loops1)Total runtime:0.097ms(3rows)现在更减少了分析函数耗费的时间 (见前面的 WindowAgg)结论在磐维数据库中不要使用row_number会有全表扫描的风险要使用标准的分页模式
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Codex 求助贴:auth.json 报错排查与 TaoToken 统一 Key 配置指南 2026/9/25 20:37:10

Codex 求助贴:auth.json 报错排查与 TaoToken 统一 Key 配置指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
数据丢失别绝望!新手速码这6种恢复方法汇总!90% 用户亲测有效! 2026/9/25 20:37:10

数据丢失别绝望!新手速码这6种恢复方法汇总!90% 用户亲测有效!

在数字时代,数据如同我们的 “数字资产”,存储着工作资料、珍贵照片、重要文档等。然而,硬盘故障、误删除、系统崩溃等意外随时可能导致数据丢失,让人措手不及。别担心!本文精心整理了 6 种实用的数据恢复方法&#xf…

阅读更多 →
ORB-SLAM3 bool Tracking::TrackWithMotionModel() 2026/9/25 20:37:04

ORB-SLAM3 bool Tracking::TrackWithMotionModel()

函数 TrackWithMotionModel() 是跟踪线程最常用的跟踪模式:恒速运动模型跟踪。它假设相机在相邻帧之间运动近似匀速,用上一帧的速度预测当前帧位姿,然后在上一帧地图点投影附近搜索匹配,仅优化当前帧位姿。 它的核心流程是: 更新上一帧的位姿和地图点关联; 若 IMU 已初…

阅读更多 →
AI 辅助 Python 排错:从多出一个空页到回归测试 2026/9/25 20:36:36

AI 辅助 Python 排错:从多出一个空页到回归测试

4 条数据,每页 2 条,分页函数却返回了 3 页,最后一页还是空的。 代码没有抛异常,接口也可能正常返回成功状态。直到调用方发现“下一页”里什么都没有,问题才暴露出来。 这类 Bug 很适合用来练习 AI 辅助排错&#x…

阅读更多 →
Agent安全:权限控制与沙箱执行 2026/9/25 20:36:09

Agent安全:权限控制与沙箱执行

Agent安全:权限控制与沙箱执行 专栏:AI/LLM工程化实战 - 从Prompt到Agent的完整落地指南 模块4 Agent工程实战篇 第42篇 摘要 摘要:Agent权限最小化、工具白名单、代码沙箱subprocess受限执行、敏感数据脱敏、审计日志,是Agent安全防护的五大核心手段。用可运行Python实现一道工…

阅读更多 →
「Python 翻车日记 · 第 12 篇」一行 read() 读 5GB,电脑就炸了?——文件是流,不是一坨 2026/9/25 20:36:02

「Python 翻车日记 · 第 12 篇」一行 read() 读 5GB,电脑就炸了?——文件是流,不是一坨

Python 翻车日记 第 12 篇:一行 read() 读 5GB,电脑就炸了?——文件是流,不是一坨 📋 本期菜单:6 个文件 I/O 的坑 + 1 个模式速查,从「read OOM」到「JSON 中文转义」 [入门] read OOM with 句柄泄漏 glob 不递归 二进制写 str [进阶] os.path.join 绝对路径丢弃 …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉