SQL 实战:分页查询的多种方式对比与优化
在处理大数据表时,分页查询是非常常见的需求。分页不仅可以提高用户体验,还能有效减少数据库查询返回的数据量,避免一次性加载大量记录引起的性能瓶颈。
然而,在数据量较大或复杂查询中,简单的分页方式可能导致性能下降。本文将探讨 SQL 中实现分页查询的不同方式,并对比它们的优缺点,帮助优化大数据量场景下的分页方案。
一、分页查询的常见方式
1. 基本分页方式:LIMIT OFFSET
- 语法:
SELECT * FROM orders
ORDER BY order_date DESC
LIMIT 10 OFFSET 20; -- 跳过前 20 条,返回第 21~30 条
- 说明:
LIMIT指定返回的行数,OFFSET指定跳过的行数。
2. 使用 ROW_NUMBER() 进行分页
- 适用数据库:MySQL 8.0 及以上、SQL Server、PostgreSQL
- 语法:
WITH ordered_orders AS ( SELECT order_id, order_date, ROW_NUMBER() OVER (ORDER BY order_date DESC) AS rn FROM orders
)
SELECT *
FROM ordered_orders
WHERE rn BETWEEN 21 AND 30;
- 说明:
ROW_NUMBER()为每一行分配唯一编号,可通过WHERE进行分页筛选。- 分页不受数据量影响,性能稳定。
3. 游标分页(基于主键或唯一索引)
- 适用场景:持续查询下一页数据,适合前端“加载更多”方式。
- 语法:
SELECT * FROM orders
WHERE order_date < '2024-01-01 00:00:00'
ORDER BY order_date DESC
LIMIT 10;
- 说明:
- 基于主键或时间字段进行分页,避免大偏移量问题,性能更优。
- 适合按时间或 ID 递增的分页加载,避免全表扫描。
4. 使用 SQL_CALC_FOUND_ROWS 计算总数
- 语法:
SELECT SQL_CALC_FOUND_ROWS * FROM orders
LIMIT 10 OFFSET 20;
SELECT FOUND_ROWS();
- 说明:
- 查询结果同时计算总行数,减少一次额外的
COUNT(*)查询。 - 在 MySQL 8.0 以后不推荐,效率较低。
- 查询结果同时计算总行数,减少一次额外的
二、实战案例:大数据分页方案设计与优化
案例 1:简单分页(LIMIT OFFSET)
需求描述:
查询订单表中按下单日期排序的第 1001-1020 条订单记录。
SQL 实现:
SELECT order_id, customer_id, order_date
FROM orders
ORDER BY order_date DESC
LIMIT 20 OFFSET 1000;
优点:
- 简单直接,适合小数据量分页。
缺点:
- 当
OFFSET较大时(如 100000),性能下降显著。 - 数据量越大,查询速度越慢,因为数据库仍需扫描前
OFFSET行。
案例 2:使用 ROW_NUMBER() 实现分页
需求描述:
查询订单表中,按订单金额降序排列的第 51-60 条记录。
SQL 实现:
WITH cte_orders AS ( SELECT order_id, amount, ROW_NUMBER() OVER (ORDER BY amount DESC) AS rn FROM orders
)
SELECT * FROM cte_orders
WHERE rn BETWEEN 51 AND 60;
优点:
- 即使数据量大,
ROW_NUMBER()也能有效避免大偏移量问题。 - 使用 CTE(公用表表达式),代码更清晰。
缺点:
- 需要 SQL 8.0 以上版本或其他支持窗口函数的数据库。
案例 3:游标方式分页(基于索引分页)
需求描述:
查询比上次加载时间更早的订单记录,每次加载 20 条记录。
SQL 实现:
SELECT order_id, customer_id, order_date
FROM orders
WHERE order_date < '2024-05-01 00:00:00'
ORDER BY order_date DESC
LIMIT 20;
优点:
- 不依赖
OFFSET,即使数据量大也能快速查询。 - 可动态加载下一页,避免重复数据查询。
缺点:
- 需要前端记录上一页最后一条数据的时间或 ID。
案例 4:SQL_CALC_FOUND_ROWS 计算总记录数
需求描述:
查询订单表第 21-40 条记录,同时返回总记录数,用于前端分页展示。
SQL 实现:
SELECT SQL_CALC_FOUND_ROWS order_id, customer_id
FROM orders
ORDER BY order_date DESC
LIMIT 20 OFFSET 20; SELECT FOUND_ROWS();
优点:
- 无需额外执行
COUNT(*)查询,减少一次数据库交互。
缺点:
- MySQL 8.0 开始弃用,
SQL_CALC_FOUND_ROWS效率较低。
三、性能对比与优化策略
1. 性能对比
| 方式 | 性能表现(小数据) | 性能表现(大数据) | 复杂性 | 推荐场景 |
|---|---|---|---|---|
LIMIT OFFSET | 高 | 低 | 简单 | 小数据量、简单分页 |
ROW_NUMBER() | 高 | 高 | 一般 | 大数据量分页、多层次筛选 |
| 游标分页 | 高 | 高 | 较复杂 | 无限加载、动态分页 |
SQL_CALC_FOUND_ROWS | 中 | 低 | 简单 | 需要总行数时(不推荐大数据量) |
2. 大数据分页优化策略
- 避免深度分页:
- 限制最大
OFFSET,提供“跳页”或“前端加载更多”方式。 - 使用游标或基于索引的分页方式逐步加载数据。
- 索引优化:
- 在分页查询涉及的字段上建立索引,提高数据检索效率。
CREATE INDEX idx_order_date ON orders(order_date);
- 改用
ROW_NUMBER():
- 对于复杂多条件查询,使用窗口函数(如
ROW_NUMBER())替代LIMIT OFFSET,能有效避免性能下降问题。
- 提前过滤数据:
- 分页前尽可能过滤不必要的数据,减少扫描行数。
SELECT * FROM orders
WHERE status = 'completed'
ORDER BY order_date DESC
LIMIT 20 OFFSET 2000;
四、总结
- 小数据量分页:使用
LIMIT OFFSET简单高效。 - 大数据量分页:优先选择游标或基于索引的分页方式,减少
OFFSET扫描行数。 - 复杂分页:使用
ROW_NUMBER()结合 CTE 实现多层次分页,性能稳定,推荐大数据环境下使用。 - 动态加载:基于唯一索引或时间字段的游标分页方式,在实际业务中更具实用性,避免性能瓶颈。
相关文章:
SQL 实战:分页查询的多种方式对比与优化
在处理大数据表时,分页查询是非常常见的需求。分页不仅可以提高用户体验,还能有效减少数据库查询返回的数据量,避免一次性加载大量记录引起的性能瓶颈。 然而,在数据量较大或复杂查询中,简单的分页方式可能导致性能下降…...
汇川Easy系列正弦信号发生器(ST源代码)
正弦余弦信号发生器CODESYS和MATLAB实现请参考下面文章链接: 正弦余弦信号发生器应用(CODESYS ST源代码+MATLAB仿真)_st语言根据输入值,形成正弦点-CSDN博客文章浏览阅读410次。本文介绍了如何在CODESYS编程环境中创建正弦和余弦信号发生器。通过详细的PLC梯形图和SCL语言代码…...
JavaSpring AI与阿里云通义大模型的集成使用Java Data Science Library(JDSL)进行数据处理
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默, 忍不住分享一下给大家。点击跳转到网站 学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……) 2、学会Oracle数据库入门到入土用法(创作中……) 3、手把…...
Three.js教程002:Three.js结合Vue进行开发
文章目录 Three.js结合Vue开发创建Vue项目安装依赖运行项目安装three使用three.js完整代码下载Three.js结合Vue开发 创建Vue项目 创建命令: npm init vite@latest框架这里选择【Vue】: 安装依赖 安装命令: cd 01-vueapp npm install运行项目 npm run dev...
pycharm+anaconda创建项目
pycharmanaconda创建项目 安装: Windows下PythonPyCharm的安装步骤及PyCharm的使用-CSDN博客 详细Anaconda安装配置环境创建教程-CSDN博客 创建项目: 开始尝试新建一个项目吧! 选择好项目建设的文件夹 我的项目命名为:pyth…...
vue2中遇到的问题与解决方案(自用)
1 、在vue2中怎么能成功渲染字符串中存在自定义组件 比如,前端样式定义后由接口返回想渲染的样式,如果此时直接使用v-html,那么vue的自定义组件或者ui框架的组件是会被直接引用不能编译成功 解决方案: 此时想到vue官网使用render函…...
CF2043b-B. Digits
题目链接 题意:给定两个整数n、d,要求找出排列成n!个d之后的数可以被1-9中奇数整除的数 题解: 主要是考察分类讨论: 被3整除,当d能被3整除时一定成立或者n > 3,当n > 3时n!一定包含因数3 被5整除&a…...
ultralytics库RT-DETR代码解析
最近读了maskformer以及maskdino的分割头设计,于是想在RT-DETR上做一个分割的改动,所以选择在ultralytics库中对RTDETR进行改进。 本文内容简介: 1.ultralytics库中RT-DETR模型解析 2. 对ultralytics库中的RT-DETR模型增加分割头做实例分割 1.ultralytics库中RT-DETR模型解…...
(七)- plane/crtc/encoder/connector objects
1,framebuffer/plane Rockchip RK3399 - DRM framebuffer、plane基础知识 - 大奥特曼打小怪兽 - 博客园 2,crtc Rockchip RK3399 - DRM crtc基础知识 - 大奥特曼打小怪兽 - 博客园 3,encoder/connector/bridge Rockchip RK3399 - DRM en…...
基于STM32的四轴飞行器的控制系统(论文+源码)
1.系统设计 本次基于stm32单片机的四轴飞行器控制系统主要包括硬件和软件这两大部分,其中硬件部分是基于单片机的四轴飞行器控制系统实现的基石,其中主要STM32单片机负责整个系统功能的实现;NRF24L01无线模块负责对四轴飞行器的远程控制&…...
混合精度训练(Mixed Precision Training)中为什么在训练过程中不直接使用bf16进行权重更新?中英双语
中文版 为什么在训练过程中不直接使用 bf16 进行权重更新? 在深度学习的训练过程中,我们通常使用 混合精度训练(Mixed Precision Training)来提高训练效率,减少内存占用。虽然 bf16(Brain Floating Point…...
【java】HashMap的实现原理
目录 1. 说明2. 哈希函数3. 桶数组4. 哈希冲突解决5. 动态扩容6. 查找、插入和删除操作 1. 说明 1.HashMap是一个基于哈希表的数据结构,它实现了Map接口。2.HashMap允许使用null键和null值,并且不保证映射的顺序。 2. 哈希函数 1.HashMap使用哈希函数…...
FCM32F103C8T6开发指引
打了块板,没有STM芯片了,于是,换了块FCM32F103C8T6.原来的工程直接编译,不能仿真,提示M3,M4核不兼容,但是,用jflash是可以直接把bin文件烧录进去的,也可以正常运行起来。 但为了方便…...
Python世界:人生苦短,我用Python
Python世界:人生苦短,我用Python 前言Python优势Python缺点 前言 几句话说清,我们为啥要用Python? Python设计之初心,是为了解决编程门槛,让大家更聚焦业务实现,而非编程细节。当前人工智能火…...
【从零开始入门unity游戏开发之——C#篇43】C#补充知识——值类型和引用类型汇总补充、变量的生命周期与性能优化、值类型和引用类型组合使用
文章目录 一、值类型和引用类型汇总补充1、值类型和引用类型汇总2、值类型和引用类型的区别3、简单的判断值类型和引用类型 二、变量的生命周期与性能优化1、**栈和堆的区别**2、**变量生命周期**3、**垃圾回收(GC)机制**4、**代码示例与优化**4.1. 临时…...
从论文到实践:Stable Diffusion模型一键生成高质量AI绘画
🏡作者主页:点击! 🤖编程探索专栏:点击! ⏰️创作时间:2024年12月24日10点02分 神秘男子影, 秘而不宣藏。 泣意深不见, 男子自持重, 子夜独自沉。 论文源地址有视频: 链接h…...
项目管理:用甘特图 “导航” 项目全程
项目全程管理是一个复杂而又系统的过程,它涵盖了从项目启动到结束的各个阶段,包括规划、执行、监控和收尾等一系列活动。 项目全程管理能够确保项目按时交付、控制成本、提高质量以及满足客户需求。通过有效的管理,项目团队可以避免资源浪费…...
v3.0.8- 「S+会员」新增专属运动秀,试试新穿搭吧- 与「好友」
v3.0.8 - 「S会员」新增专属运动秀,试试新穿搭吧 - 与「好友」互动支持前往对方所在的「在线运动房」 - 「运动秀工坊」新增智能背景抠图 - 「体育竞技」匹配中可以看到我和对手的装备 - 多项界面体验和性能优化 v2.0.17 - 班级运动场新增运动秀展示 - 班级玩法&…...
9-Gin 中自定义 Model --[Gin 框架入门精讲与实战案例]
在 Gin 框架中自定义 Model 通常指的是定义你自己的数据结构,这些结构体(Structs)将用来表示数据库中的表、API 请求的参数或响应的数据格式。下面是如何在 Gin 中创建和使用自定义 Model 的基本步骤。 自定义 Model 定义结构体 首先&…...
【VBA】EXCEL - VBA 创建 Sheet 表的 6 种方法,以及注意事项
目录 1. 创建一个新工作表,并将其添加到工作簿的末尾 2. 创建一个新工作表,并命名它 3. 创建一个新工作表,并将其插入到指定位置 4. 检查是否已有同名工作表,避免重复创建 5. 创建多个工作表 6. 基于现有模板创建新工作表 …...
C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...
Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...
三分算法与DeepSeek辅助证明是单峰函数
前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...
毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...
