0

0

如何在SQL中实现分页查询?OFFSET与FETCH的正确用法

雪夜

雪夜

发布时间:2025-09-04 19:19:01

|

399人浏览过

|

来源于php中文网

原创

答案是使用OFFSET和FETCH NEXT结合ORDER BY实现分页,核心在于通过ORDER BY确保排序确定性,OFFSET跳过指定行数,FETCH NEXT获取所需行数;例如SELECT column FROM table ORDER BY col OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY可获取第2页数据(每页10条);相比LIMIT/OFFSET,OFFSET/FETCH符合SQL标准且适用于SQL Server等数据库;但大偏移量时性能差,因需扫描跳过行;解决方法包括键集分页(利用上一页最后ID作为下一页起点)、为ORDER BY列建立索引、根据访问模式选择分页策略,以及使用缓存或物化视图优化频繁查询。

如何在sql中实现分页查询?offset与fetch的正确用法

在SQL中实现分页查询,现代且标准的方法是利用

OFFSET
FETCH NEXT
子句。它允许你跳过指定数量的行,然后获取接下来的若干行,这对于构建用户界面中的数据列表或API分页非常有效。

解决方案

实现分页查询,核心在于结合

ORDER BY
OFFSET
FETCH NEXT
ORDER BY
是不可或缺的,因为它决定了行的顺序,没有它,分页结果将是不可预测的。

一个基本的分页查询通常看起来像这样:

SELECT column1, column2, ...
FROM YourTable
ORDER BY YourSortColumn ASC/DESC
OFFSET @PageNumber * @PageSize ROWS -- 跳过多少行
FETCH NEXT @PageSize ROWS ONLY;      -- 获取多少行

这里,

@PageNumber
通常是从0开始的页码(或者从1开始,但计算时需要调整),
@PageSize
是每页显示的记录数。例如,要获取第二页(假设页码从0开始,每页10条),
@PageNumber
就是1,
@PageSize
就是10,那么
OFFSET
就是10,
FETCH NEXT
就是10。

为什么传统的LIMIT/OFFSET在某些场景下不再是最佳选择?

说实话,当我们谈到分页,很多开发者脑子里第一反应可能是

LIMIT
OFFSET
。这在MySQL和PostgreSQL中确实很常见,也很好用。但如果你在SQL Server或者Oracle这样的环境中工作,或者希望遵循更广泛的SQL标准,
OFFSET
FETCH NEXT
就显得更“正统”一些。我个人觉得,
LIMIT/OFFSET
虽然简洁,但在不同数据库间的语法差异确实是个小麻烦,比如SQL Server就没有直接的
LIMIT

更重要的是,

LIMIT/OFFSET
(以及
OFFSET/FETCH
)在处理非常大的偏移量时,性能可能会遇到瓶颈。数据库需要先处理(甚至排序)所有被跳过的行,即使我们最终并不需要它们。这就像你要从一本很厚的书里找第1000页的第10行,你还是得先翻过前面999页。对于小数据集或者浅层分页,这问题不大,但对于百万级甚至千万级数据,而且用户可能想跳到很后面的页面时,性能下降会非常明显。

另一个我常强调的点是,无论是哪种分页方式,

ORDER BY
都必须有。没有它,数据库返回的行顺序是不确定的。今天你看到的“第一页”数据,明天可能就完全不同了,这在实际应用中是绝对不能接受的。我见过不少新手开发者忽略了这一点,导致用户界面数据跳来跳去,非常困扰。

OFFSET FETCH NEXT的实际应用与常见陷阱

OFFSET FETCH NEXT
在实际开发中简直是标配。无论是Web应用的数据表格、移动端App的列表,还是后台管理系统的报表,只要需要分批加载数据,它都能派上用场。我经常用它来实现“无限滚动”效果,用户滚动到底部时,就加载下一页数据。

Getimg.ai
Getimg.ai

getimg.ai是一套神奇的ai工具。生成大规模的原始图像

下载

然而,在使用过程中,有一些坑是我们需要特别留意的:

首先,我必须再次强调,缺少

ORDER BY
是最大的陷阱。没有它,你的分页结果将是混乱且不可预测的。数据库可能根据内部存储顺序、查询计划或其他非确定性因素返回数据,这会导致用户看到重复数据或漏掉某些数据。比如,你查询“商品列表”,第一页是A、B、C,第二页是D、E、F。如果没
ORDER BY
,下次刷新,第一页可能就变成D、A、C了,完全乱套。

其次,大偏移量下的性能问题。正如前面提到的,即使是

OFFSET FETCH NEXT
,如果
OFFSET
值非常大,数据库仍然需要扫描或排序大量的行才能到达你想要的起点。这会消耗大量的CPU和I/O资源。我曾经在一个项目中遇到过,用户尝试直接跳转到几千页之后,整个查询直接超时,导致用户体验极差。这时候,我们可能需要考虑更高级的优化手段。

再者,并发修改导致的数据不一致。设想一下,你在获取第一页数据后,有新的数据被插入或旧数据被删除。当你请求第二页时,由于数据行的增减,你可能会看到第一页的最后几条数据再次出现在第二页,或者直接跳过了一些数据。这种情况在数据更新频繁的系统中尤为常见。这通常需要应用层的一些策略来缓解,比如使用快照隔离级别,或者基于时间戳/ID的“游标分页”方式。

-- 一个带有ORDER BY的正确分页示例
SELECT ProductID, ProductName, Price
FROM Products
WHERE CategoryID = 101
ORDER BY Price DESC, ProductID ASC -- 先按价格降序,再按ID升序,确保唯一排序
OFFSET 20 ROWS                      -- 跳过前20条记录
FETCH NEXT 10 ROWS ONLY;            -- 获取接下来的10条记录

优化大型数据集分页查询的策略与思考

OFFSET FETCH NEXT
大数据集下开始显得力不从心时,我们不能坐以待毙。这里有一些我个人实践中觉得非常有效的策略:

1. 键集分页(Keyset Pagination),也被称为“游标分页”或“Seek Method”: 这是我处理深层分页的首选方案。它不依赖于行数偏移,而是依赖于“上一页最后一条记录的某个唯一标识符”。例如,如果你的数据是按

ID
排序的,那么下一页的查询条件就是
WHERE ID > [上一页最后一条记录的ID] ORDER BY ID ASC LIMIT N
。 这种方式的优点是数据库不需要扫描所有被跳过的行,它直接“跳”到你上次停止的地方。性能提升是巨大的,因为它能充分利用索引。缺点是它通常只能“下一页”,不能直接跳到任意页,或者“上一页”的逻辑会稍微复杂一点。

-- 键集分页示例 (假设ProductID是唯一的,且按此排序)
SELECT ProductID, ProductName, Price
FROM Products
WHERE ProductID > @LastProductIDOnPreviousPage -- @LastProductIDOnPreviousPage 是上一页最后一条记录的ProductID
ORDER BY ProductID ASC
FETCH NEXT 10 ROWS ONLY;

2. 确保

ORDER BY
列有合适的索引: 无论你用哪种分页方式,如果
ORDER BY
子句中的列没有索引,数据库就不得不进行全表扫描和内存排序,这会极大地拖慢查询速度。为排序字段创建复合索引(如果排序涉及多个列)是基础中的基础。

3. 考虑数据访问模式: 如果用户很少会翻到很深的页面,那么简单的

OFFSET FETCH NEXT
可能就足够了。但如果用户经常需要跳转到任意页,或者进行无限滚动,那么键集分页就更合适。了解你的用户如何与数据交互,是选择优化策略的关键。

4. 缓存或物化视图: 对于那些变化不频繁但查询量很大的分页数据,可以考虑在应用层进行缓存,或者在数据库层面创建物化视图(Materialized View)来预先计算和存储分页结果。当然,这会引入数据新鲜度的问题,需要权衡。

在我看来,SQL分页查询不仅仅是写几行代码那么简单,它背后是对数据量、查询模式和数据库性能的综合考量。没有一劳永逸的“最佳”方案,只有最适合当前场景的解决方案。有时候,即使是最简单的

OFFSET FETCH NEXT
,只要配合好索引和合理的页大小,也能跑得很好。但当数据量上来,或者用户需求变得复杂时,我们就要准备好掏出更“高级”的工具了。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

727

2023.10.12

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

327

2023.10.27

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

350

2024.02.23

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

1242

2024.03.06

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

360

2024.03.06

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

820

2024.04.07

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

581

2024.04.29

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

423

2024.04.29

俄罗斯Yandex引擎入口
俄罗斯Yandex引擎入口

2026年俄罗斯Yandex搜索引擎最新入口汇总,涵盖免登录、多语言支持、无广告视频播放及本地化服务等核心功能。阅读专题下面的文章了解更多详细内容。

158

2026.01.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
R 教程
R 教程

共45课时 | 5.7万人学习

SQL 教程
SQL 教程

共61课时 | 3.6万人学习

C 教程
C 教程

共75课时 | 4.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号