因为专注所以专业
助力成长与创新,汇集前沿程序开发观点

订单列表滚到很后面就转圈,offset 越大越慢,能不能只把每页条数调小?

2026年9月29日 阅读:36

订单列表滚到后面越来越慢,通常不是每页条数设大了,而是 limit offset 要先把前面大量行扫出来再丢掉,offset 越大越慢。按 2026 年项目交付经验,订单流水、操作日志这类主要靠连续往下翻的列表,常见做法是改成基于有序且不重复字段的游标分页;但需要任意跳页、精确总页数的报表接口,不适合硬改,否则问题会从前端或统计口径冒出来。

为什么 offset 越大越慢,调小每页条数为什么救不了

先看语义。limit 100000, 20 不是直接跳到第 100000 行,而是从符合条件的第一行开始数,数到第 100000 行之后才取 20 行。即使查询用上索引,数据库也要沿着索引走大量行,再把前面的行丢弃。成本跟 offset 大小走,不跟每页条数走。

常见误区是「把 pageSize 从 50 改成 20,接口就会快」。每页条数只影响最后返回和网络传输,前面被扫描丢弃的行数几乎没变。经验区间:数据量几万行、翻页几十页以内,差异可能不明显;到几十万行、offset 到几万甚至十几万时,单次查询从几十毫秒涨到几百毫秒以上是常见现象,具体受硬件、索引覆盖、过滤条件和排序方式影响。

  • 翻到第 N 页的耗时大致随 N 增长,不是随 pageSize 增长。
  • 排序字段没有合适索引时,数据库还要额外排序,深翻页更明显。
  • 列表带 status、tenant_id 等过滤条件时,回表次数和扫描行数会叠加。

在深翻页场景里,offset 是成本变量,不是普通分页参数;调小每页条数改的是最后一小段,改不了前面的大扫描。

游标分页和 limit offset 的差别在哪

游标分页不数前面的行,而是拿上一页最后一条记录的有序键值当起点。例如按 ID 倒序时写成 where id < 上一页最后一条 id order by id desc limit 20。数据库可以直接用索引定位到起点,再往后取一页,翻页深度对单次查询耗时影响通常小得多。

  • 定位方式:offset 数行丢弃,游标按有序键直接定位。
  • 翻页深度影响:offset 随页数增长,游标在排序稳定时基本平稳。
  • 跳页能力:offset 支持跳到任意页码,游标通常只能上一页或下一页。
  • 排序字段要求:offset 对排序字段要求低,游标必须有序且能保证不重复。
  • 总数统计:offset 容易配套 count,游标要另算总数或只给是否还有下一页。
  • 适用对象:offset 适合后台报表、需要页码的列表;游标适合订单流水、消息流、日志流。

游标分页不是更高级的分页,它只是把按位置翻页换成按值翻页,代价是失去跳页和精确页码。

哪些订单列表适合改游标分页,哪些不适合

判断标准不是接口有没有慢,而是业务是否需要任意跳页。如果运营主要连续往下看最近订单,跳到第 50 页的需求很少,深翻页就是可以省掉的成本。反过来,如果报表页必须直接跳页、还要显示共多少页,游标分页会把这些需求推给另一套逻辑,不一定划算。

适合改的情况:

  • 按创建时间或 ID 倒序的流水列表,用户连续往下翻。
  • 单页数据量偏大、翻页深度经常超过几十页。
  • 排序字段不重复,或可用「时间 + ID」组合保证不重复。
  • 前端是滚动加载或加载更多,不依赖页码跳转。

不适合改的情况:

  • 需要直接跳到指定页码的运营报表。
  • 必须展示精确总页数或总条数的场景。
  • 排序字段可随意切换,且找不到稳定不重复键。
  • 数据量很小、翻页很浅,经验区间是万级以内时,改造收益不明显。

如果业务不需要跳页,深翻页就是一笔可以砍掉的成本;如果需要跳页,硬改游标往往只是把问题挪到前端或统计口径。

落地游标分页要先核对哪些字段和口径

游标分页的代码量不大,难点在字段选择和接口契约。按交付习惯,可以先走一套四步核对法,把丢记录、重复记录和兼容问题提前挡住。

  1. 确定有序不重复键:单列自增 ID 比较省事;如果按创建时间排序,用 (create_time, id) 组合,避免同一时间多条记录被跳过或重复。
  2. 明确游标传递:接口返回 next_cursor 和 has_more,前端原样回传,不要让前端自己拼页码或加减。
  3. 处理边界:第一页不传游标;最后一页返回 has_more=false;反向翻页时比较符号要反过来。
  4. 保留兼容:旧 offset 接口并行一段时间,新老客户端分别对接,等覆盖率上来再下线。

这样划分的原因是:有序键决定不丢不重,游标传递决定前后端理解一致,边界决定最后一页体验,兼容决定发布风险。排序和索引行为可按所用数据库官方文档核对,不要凭感觉假设。

交付现场:只改一个流水列表的约束和代价

交付现场常见约束是「预算和周期只够改一个列表,运营又要求最近三个月订单按时间倒序连续翻」。2026 年常见做法是先只改订单流水接口,保留原 offset 接口给需要跳页的导出页。

可核对对比(经验区间,不是固定报价):只加索引或裁剪字段,常见投入约半天到 1 人日,浅翻页和带过滤条件时有帮助,深翻页收益有限;改造为游标分页,常见投入约 1 到 2 人日开发、半天联调,连续翻页耗时更平稳,但要补 has_more 和游标契约;导出链路另拆,常见投入约 2 到 3 人日,能减轻接口内存和超时压力,但周期更长。代价是导出页或跳页报表仍然慢,需要后续再拆。

游标分页的验收口径不是「接口不超时」,而是「翻到任意深度耗时稳定、不丢记录、不重复记录、老客户端不报错」。

常见问题

只把每页条数调小,能不能解决深翻页慢?

通常不能。每页条数只影响最后返回和网络传输,offset 前面要扫描丢弃的行数没变,深翻页成本仍在。

游标分页是不是一定要用自增 ID?

不是。自增 ID 只是比较省事的有序不重复键;用创建时间加 ID 组合也可以,关键是排序结果稳定且不重复。

改成游标分页以后还能显示总页数吗?

精确总页数要另做 count 或近似统计;深翻页场景下建议只显示「加载更多」,不要强行算总页数。

数据量不大也要改成游标分页吗?

不必。经验区间是万级以内、翻页深度浅时,limit offset 通常够用,改造反而增加联调成本。

老客户端还在用 page 参数怎么办?

可保留旧 offset 接口一段时间,新接口并行提供,等客户端覆盖率上来再下线,避免直接切换导致老版本报错。


行动指引:先拉线上深翻页请求的 offset 分布和 P95 耗时。如果多数请求集中在前几页,优先做索引和字段裁剪;只有翻页深度稳定超过几十页、且业务不需要跳页时,再按游标分页改造。适用边界:需要精确页码、任意跳页或排序不稳定的报表类接口,不建议强行改造,可继续用 offset 并单独优化导出链路。不适用边界:排序键重复、数据量小且翻页浅、接口契约暂时无法加游标字段时,先别硬改。

有类似的项目需求?
联系我们,获取一对一项目参考方案
获取方案
准备好开始了吗,
那就与我们取得联系吧!
13370032918
了解更多服务,随时联系我们
请填写您的需求
您希望我们为您提供什么服务呢
您的预算
联
系
微信二维码
扫码添加客服微信
专业对接各类技术问题
联系电话
13370032918 (金经理)
电话若占线或未接到、就加下微信
联系邮箱
349077570@qq.com
提交成功
感谢您的信任,我们会尽快与您联系!
为您推荐以下案例