当前位置: 首页 > news >正文

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. 大数据分页优化策略
  1. 避免深度分页
  • 限制最大 OFFSET,提供“跳页”或“前端加载更多”方式。
  • 使用游标或基于索引的分页方式逐步加载数据。
  1. 索引优化
  • 在分页查询涉及的字段上建立索引,提高数据检索效率。
CREATE INDEX idx_order_date ON orders(order_date);
  1. 改用 ROW_NUMBER()
  • 对于复杂多条件查询,使用窗口函数(如 ROW_NUMBER())替代 LIMIT OFFSET,能有效避免性能下降问题。
  1. 提前过滤数据
  • 分页前尽可能过滤不必要的数据,减少扫描行数。
SELECT * FROM orders  
WHERE status = 'completed'  
ORDER BY order_date DESC  
LIMIT 20 OFFSET 2000;


四、总结

  • 小数据量分页:使用 LIMIT OFFSET 简单高效。
  • 大数据量分页:优先选择游标或基于索引的分页方式,减少 OFFSET 扫描行数。
  • 复杂分页:使用 ROW_NUMBER() 结合 CTE 实现多层次分页,性能稳定,推荐大数据环境下使用。
  • 动态加载:基于唯一索引或时间字段的游标分页方式,在实际业务中更具实用性,避免性能瓶颈。

相关文章:

SQL 实战:分页查询的多种方式对比与优化

在处理大数据表时&#xff0c;分页查询是非常常见的需求。分页不仅可以提高用户体验&#xff0c;还能有效减少数据库查询返回的数据量&#xff0c;避免一次性加载大量记录引起的性能瓶颈。 然而&#xff0c;在数据量较大或复杂查询中&#xff0c;简单的分页方式可能导致性能下降…...

汇川Easy系列正弦信号发生器(ST源代码)

正弦余弦信号发生器CODESYS和MATLAB实现请参考下面文章链接: 正弦余弦信号发生器应用(CODESYS ST源代码+MATLAB仿真)_st语言根据输入值,形成正弦点-CSDN博客文章浏览阅读410次。本文介绍了如何在CODESYS编程环境中创建正弦和余弦信号发生器。通过详细的PLC梯形图和SCL语言代码…...

JavaSpring AI与阿里云通义大模型的集成使用Java Data Science Library(JDSL)进行数据处理

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c; 忍不住分享一下给大家。点击跳转到网站 学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……&#xff09; 2、学会Oracle数据库入门到入土用法(创作中……&#xff09; 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创建项目 安装&#xff1a; Windows下PythonPyCharm的安装步骤及PyCharm的使用-CSDN博客 详细Anaconda安装配置环境创建教程-CSDN博客 创建项目&#xff1a; 开始尝试新建一个项目吧&#xff01; 选择好项目建设的文件夹 我的项目命名为&#xff1a;pyth…...

vue2中遇到的问题与解决方案(自用)

1 、在vue2中怎么能成功渲染字符串中存在自定义组件 比如&#xff0c;前端样式定义后由接口返回想渲染的样式&#xff0c;如果此时直接使用v-html&#xff0c;那么vue的自定义组件或者ui框架的组件是会被直接引用不能编译成功 解决方案&#xff1a; 此时想到vue官网使用render函…...

CF2043b-B. Digits

题目链接 题意&#xff1a;给定两个整数n、d&#xff0c;要求找出排列成n!个d之后的数可以被1-9中奇数整除的数 题解&#xff1a; 主要是考察分类讨论&#xff1a; 被3整除&#xff0c;当d能被3整除时一定成立或者n > 3&#xff0c;当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&#xff0c;framebuffer/plane Rockchip RK3399 - DRM framebuffer、plane基础知识 - 大奥特曼打小怪兽 - 博客园 2&#xff0c;crtc Rockchip RK3399 - DRM crtc基础知识 - 大奥特曼打小怪兽 - 博客园 3&#xff0c;encoder/connector/bridge Rockchip RK3399 - DRM en…...

基于STM32的四轴飞行器的控制系统(论文+源码)

1.系统设计 本次基于stm32单片机的四轴飞行器控制系统主要包括硬件和软件这两大部分&#xff0c;其中硬件部分是基于单片机的四轴飞行器控制系统实现的基石&#xff0c;其中主要STM32单片机负责整个系统功能的实现&#xff1b;NRF24L01无线模块负责对四轴飞行器的远程控制&…...

混合精度训练(Mixed Precision Training)中为什么在训练过程中不直接使用bf16进行权重更新?中英双语

中文版 为什么在训练过程中不直接使用 bf16 进行权重更新&#xff1f; 在深度学习的训练过程中&#xff0c;我们通常使用 混合精度训练&#xff08;Mixed Precision Training&#xff09;来提高训练效率&#xff0c;减少内存占用。虽然 bf16&#xff08;Brain Floating Point…...

【java】HashMap的实现原理

目录 1. 说明2. 哈希函数3. 桶数组4. 哈希冲突解决5. 动态扩容6. 查找、插入和删除操作 1. 说明 1.HashMap是一个基于哈希表的数据结构&#xff0c;它实现了Map接口。2.HashMap允许使用null键和null值&#xff0c;并且不保证映射的顺序。 2. 哈希函数 1.HashMap使用哈希函数…...

FCM32F103C8T6开发指引

打了块板&#xff0c;没有STM芯片了&#xff0c;于是&#xff0c;换了块FCM32F103C8T6.原来的工程直接编译&#xff0c;不能仿真&#xff0c;提示M3,M4核不兼容&#xff0c;但是&#xff0c;用jflash是可以直接把bin文件烧录进去的&#xff0c;也可以正常运行起来。 但为了方便…...

Python世界:人生苦短,我用Python

Python世界&#xff1a;人生苦短&#xff0c;我用Python 前言Python优势Python缺点 前言 几句话说清&#xff0c;我们为啥要用Python&#xff1f; Python设计之初心&#xff0c;是为了解决编程门槛&#xff0c;让大家更聚焦业务实现&#xff0c;而非编程细节。当前人工智能火…...

【从零开始入门unity游戏开发之——C#篇43】C#补充知识——值类型和引用类型汇总补充、变量的生命周期与性能优化、值类型和引用类型组合使用

文章目录 一、值类型和引用类型汇总补充1、值类型和引用类型汇总2、值类型和引用类型的区别3、简单的判断值类型和引用类型 二、变量的生命周期与性能优化1、**栈和堆的区别**2、**变量生命周期**3、**垃圾回收&#xff08;GC&#xff09;机制**4、**代码示例与优化**4.1. 临时…...

从论文到实践:Stable Diffusion模型一键生成高质量AI绘画

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;编程探索专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年12月24日10点02分 神秘男子影, 秘而不宣藏。 泣意深不见, 男子自持重, 子夜独自沉。 论文源地址有视频&#xff1a; 链接h…...

项目管理:用甘特图 “导航” 项目全程

项目全程管理是一个复杂而又系统的过程&#xff0c;它涵盖了从项目启动到结束的各个阶段&#xff0c;包括规划、执行、监控和收尾等一系列活动。 项目全程管理能够确保项目按时交付、控制成本、提高质量以及满足客户需求。通过有效的管理&#xff0c;项目团队可以避免资源浪费…...

v3.0.8- 「S+会员」新增专属运动秀,试试新穿搭吧- 与「好友」

v3.0.8 - 「S会员」新增专属运动秀&#xff0c;试试新穿搭吧 - 与「好友」互动支持前往对方所在的「在线运动房」 - 「运动秀工坊」新增智能背景抠图 - 「体育竞技」匹配中可以看到我和对手的装备 - 多项界面体验和性能优化 v2.0.17 - 班级运动场新增运动秀展示 - 班级玩法&…...

9-Gin 中自定义 Model --[Gin 框架入门精讲与实战案例]

在 Gin 框架中自定义 Model 通常指的是定义你自己的数据结构&#xff0c;这些结构体&#xff08;Structs&#xff09;将用来表示数据库中的表、API 请求的参数或响应的数据格式。下面是如何在 Gin 中创建和使用自定义 Model 的基本步骤。 自定义 Model 定义结构体 首先&…...

【VBA】EXCEL - VBA 创建 Sheet 表的 6 种方法,以及注意事项

目录 1. 创建一个新工作表&#xff0c;并将其添加到工作簿的末尾 2. 创建一个新工作表&#xff0c;并命名它 3. 创建一个新工作表&#xff0c;并将其插入到指定位置 4. 检查是否已有同名工作表&#xff0c;避免重复创建 5. 创建多个工作表 6. 基于现有模板创建新工作表 …...

多车环境下车载毫米波雷达是否会相互干扰?

在汽车工业迈向智能化与自动化的进程中&#xff0c;毫米波雷达已然成为了车辆感知体系中不可或缺的一部分。这种波长介于1毫米至10毫米之间的电磁波进行探测的装置&#xff0c;凭借其能够穿透雨雪、浓雾及强光直射的全天候工作能力&#xff0c;为高级驾驶辅助系统提供了关键的距…...

hello-uniapp图片懒加载实现:优化应用性能与流量的完整指南

hello-uniapp图片懒加载实现&#xff1a;优化应用性能与流量的完整指南 【免费下载链接】hello-uniapp uni-app框架演示示例 项目地址: https://gitcode.com/gh_mirrors/he/hello-uniapp 在移动应用开发中&#xff0c;图片加载是影响性能和用户体验的关键因素。hello-un…...

安卓音频问题解决记录(一)

本文记录在安卓framework开发过程中遇到的一些音频问题的解决办法。 1.支持多应用同时录音(安卓10以上) 通过日志分析,发现当另一个应用打开录音的时候会被静音,日志如下: APM_AudioPolicyManager: setAppState(portId:43, state:2) APM_AudioPolicyManager: set…...

FALCON: Fast Autonomous Aerial ExplorationUsing Coverage Path Guidance(覆盖路径引导的快速自主空中探索)

创新点&#xff1a;提出一种基于连接性的增量式空间分解和连接图构造方法&#xff0c;捕获环境拓扑并促进有效的探测覆盖路径规划提出一种分层的探索规划方法&#xff0c;生成合理的覆盖路径作为全局指导&#xff0c;并优化局部边界访问顺序&#xff0c;保持覆盖路径的意图。提…...

桥式电路(三)开尔文电桥在功率半导体中的实战解析

1. 从测量误差到功率革命&#xff1a;开尔文电桥的前世今生 1862年的实验室里&#xff0c;威廉汤姆森&#xff08;后来的开尔文勋爵&#xff09;正为小电阻测量中的诡异误差头疼不已。他发现当被测电阻低于1Ω时&#xff0c;连接点的接触电阻和引线电阻会彻底扭曲测量结果——这…...

Cursor Free VIP:彻底解决AI编程助手使用限制的智能解决方案

Cursor Free VIP&#xff1a;彻底解决AI编程助手使用限制的智能解决方案 【免费下载链接】cursor-free-vip [Support 0.45]&#xff08;Multi Language 多语言&#xff09;自动注册 Cursor Ai &#xff0c;自动重置机器ID &#xff0c; 免费升级使用Pro 功能: Youve reached yo…...

3步永久保存青春记忆:GetQzonehistory让QQ空间数据永不消逝

3步永久保存青春记忆&#xff1a;GetQzonehistory让QQ空间数据永不消逝 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 你的数字回忆正在流失吗&#xff1f; 每天有超过10万条QQ空间动…...

破解Python加密包:PyInstxtractor的逆向侦探手记

破解Python加密包&#xff1a;PyInstxtractor的逆向侦探手记 【免费下载链接】pyinstxtractor PyInstaller Extractor 项目地址: https://gitcode.com/gh_mirrors/py/pyinstxtractor 作为一名逆向工程师&#xff0c;我经常遇到被PyInstaller加密打包的Python可执行文件。…...

3大核心功能解锁QtScrcpy:实现跨平台Android设备高效控制

3大核心功能解锁QtScrcpy&#xff1a;实现跨平台Android设备高效控制 【免费下载链接】QtScrcpy Android real-time display control software 项目地址: https://gitcode.com/GitHub_Trending/qt/QtScrcpy QtScrcpy是一款开源的跨平台Android实时显示与控制工具&#x…...

tealdeer与其他tldr客户端的终极对比分析:哪个更适合你的命令行工作流?

tealdeer与其他tldr客户端的终极对比分析&#xff1a;哪个更适合你的命令行工作流&#xff1f; 【免费下载链接】tealdeer A very fast implementation of tldr in Rust. 项目地址: https://gitcode.com/gh_mirrors/te/tealdeer tealdeer是一款用Rust开发的tldr客户端&a…...