尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
分页语句使用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

相关推荐

Blender接入Hyper3D Rodin的MCP协议实战指南

Blender接入Hyper3D Rodin的MCP协议实战指南

1. 这不是“一键生成3D”,而是打通AI与建模工作流的真实链路你搜“Blender MCP 接入 Hyper3D Rodin 教程”,点开十篇,八篇在讲“如何注册OpenRouter”、两篇贴了张模糊截图说“配置完就能用”。结果装完插件,点一下“生成”&#…

📅 2026/9/25 19:16:47
NVIDIA驱动回滚避坑指南:精准版本筛选与安全降级实战

NVIDIA驱动回滚避坑指南:精准版本筛选与安全降级实战

1. 为什么“回滚驱动”会变成一场灾难?——从三个真实翻车现场说起NVIDIA 官方历史版本驱动下载,听起来只是点几下鼠标的事。但如果你最近试过在 RTX 4060 笔记本上卸载 536.99 驱动、想退回 528.49 来解决黑屏问题,或者在 Ubuntu 20.04 上重…

📅 2026/9/25 19:16:47
JSP+MySQL个人记事本全解析:从Servlet到WAR部署实践

JSP+MySQL个人记事本全解析:从Servlet到WAR部署实践

简介:这是一套基于JSP与MySQL实现的个人记事备忘系统源码,适合Java Web初学者、课程设计者及需要快速搭建笔记类应用的开发者。系统围绕在线记事场景,实现了笔记的创建、编辑、存储与检索,并清晰展示了JSP动态页面、Servlet请求处…

📅 2026/9/25 19:16:47
MORE NEWS

更多资讯

📰

华为 分阶段发布应用

一、分阶段发布在当前上架版本为全网发布时,可以采用分阶段发布的方式进行应用升级。采用分阶段发布,可以先向一定比例的用户发布更新的版本,然后再逐步提升用户比例,最终实现全网发布。核心价值:通过小范围的版本更新…

📰

有哪些科研工具

科研工具涵盖‌软件与硬件两大类‌,按功能可分为文献管理、检索、数据分析、绘图、编程、AI 工具及实验仪器等 。‌‌ 一、常用软件工具 1、‌文献管理‌: EndNote、Zotero、小绿鲸、NoteExpress、Mendeley,支持文献整理、引用生成和团队协作…

📰

GlusterFS 集群部署记录 文档

部署日期:2026-09-22 部署方式:基于项目脚本(GFS脚本-尹斌)自动化执行 软件版本:CentOS 7.9 GlusterFS 7.9一、集群拓扑主机名IP角色数据盘brick 路径状态node110.10.10.41存储节点/dev/sdb~sde(各10G&…

📰

Atlas 300V 24G推理加速卡部署YOLO实战:模型转换与ACL推理全解析

Atlas这个代号,在AI硬件圈子里这几年越来越常见。最近后台也老有人问“atlas 300v 24g是运算加速卡吗”“atlas部署yolo到底怎么搞”——我一开始接触Atlas 300V 24G的时候也有同样的疑惑,因为它外观和普通显卡摆在一起实在太像了,但本质上这…

📰

肌电信号分类数据集与代码:从预处理到SVM/CNN的完整流水线

简介:这份资源面向生物医学工程、康复医学与人机交互方向的学习者和研究者,围绕表面肌电信号(sEMG)分类任务,提供数据集与配套代码,帮助读者理解肌肉运动状态分析在医疗诊断、假肢控制与运动分析中的应用。…

📰

GO [ 映射表 ]

前面我们已经学习了 Go 的变量、常量、数据类型、输入输出、条件控制、切片和字符串。接下来开始学习 Go 语言中非常重要的一种集合类型:映射表,也就是 map。 很多初学者会把 map 理解成“可以用字符串做下标的数组”。这个理解不准确。按照 Go 官方语言…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬