求解深分页问题,last pk适合什么情况

在 MySQL 中,"深分页"是一个非常头疼的问题。当我们执行 LIMIT 1000000, 10 时,数据库并不是直接跳到第 100 万行,而是扫描前 1,000,010 行,然后扔掉前 1,000,000 行。这会导致大量的随机 I/O 和回表操作,性能极差。

你提到的 last pk(上一次主键 ID) 方案,也就是业内常说的"滚动分页""寻路法(Seek Method)"。


1. 核心逻辑

这种方案的本质是:利用索引的有序性,直接定位到下一页的起点。

  • 普通分页: SELECT * FROM table WHERE ... LIMIT 1000000, 10;(慢,扫描 100 万行)
  • last pk 分页: SELECT * FROM table WHERE id > 1000000 LIMIT 10;(快,直接从 ID=1000000 处开始扫描)

2. last pk 适合什么情况?

这个方案虽然快,但它对业务场景有比较严格的要求:

A. 适合"下一页"模式(流式展示)

这是它最完美的应用场景。比如:

  • 社交媒体信息流: 抖音、微博、朋友圈。你只会不停地往下滑,而不会突然跳到第 100 页。
  • 实时日志查看: 按照时间顺序(或自增 ID)一条条加载。
B. 适合大数据量的全表扫描/数据迁移
  • 如果你需要把几亿条数据从 MySQL 抽取到 ElasticSearch 或者进行 ETL 处理,用 LIMIT offset 会越跑越慢,甚至拖垮数据库。
  • 使用 WHERE id > last_id 可以保证整个抽取过程的响应时间是平稳的。
C. 适合排序字段是主键或有唯一索引的场景
  • 因为它是基于"上一个 ID"来寻路的,如果排序字段不是 ID(比如按"修改时间"排序),且时间有大量重复,逻辑就会变得复杂(需要 WHERE (time < last_time) OR (time = last_time AND id < last_id))。

3. last pk 的局限性(不适合的情况)

  1. 不适合"跳页"查询:
  • 如果你要求用户能直接点击"第 500 页",这种方案就瞎了。因为你没法在不扫描的情况下知道第 499 页的最后一个 ID 是多少。
  1. 主键必须有序(或排序字段稳定):
  • 如果数据频繁删除导致 ID 极其不连续,虽然不影响性能,但在某些需要精确计算步长的业务场景下可能会有小麻烦。

4. 补充:如果必须要"跳页"怎么办?

如果业务强制要求深分页且必须支持跳页,通常有两种折中方案:

  • 方案一:延迟关联(Deferred Join)
    先通过覆盖索引只查找主键,减少回表。
sql 复制代码
SELECT * FROM table t1 
INNER JOIN (SELECT id FROM table WHERE ... LIMIT 1000000, 10) t2 
ON t1.id = t2.id;

在二级索引树里面遍历索引树找id,跳过签100万个id返回10个id,然后10个id再联表查询

原理:在内查询里只走索引不回表,等确定了这 10 个 ID 后再回表,效率提升巨大。

  • 方案二:限制最大翻页数
    这也是大厂常用的办法(如百度、谷歌、京东)。你会发现它们通常只让你翻到 100 页左右,后面的数据就不给看了。

总结

last pk 是解决深分页性能问题的"银弹" ,但它牺牲了"自由跳页"的功能。如果你的场景是瀑布流、滚动加载或批量数据处理 ,请务必使用 last pk 方案。

你现在的业务场景是属于用户侧的列表展示,还是后台的数据处理任务?

相关推荐
慧一居士3 小时前
ThreadLocal 功能及使用场景介绍,使用详解
java
zh73143 小时前
typephp的编译核心phpx原理解析
android·java·开发语言
2401_894915535 小时前
GEO 优化源码全解析:从搜索引擎到 AI 引擎的底层改写逻辑
java·服务器·前端·数据库·人工智能·分布式·搜索引擎
Java牛马9 小时前
SpringBoot Starter 依赖相关总结
java·spring·springboot·starter·自动装配·依赖
吴声子夜歌10 小时前
Java面试——Spring Cloud原理及应用(二)
java·spring cloud·面试
东小西10 小时前
【SAA实战】第 1 篇:ReactAgent 入门——先撸个"会调工具的助手"跑起来
java·人工智能·spring
xrandzj11 小时前
MySQL8.0 从零通关核心操作手册(Ubuntu实战版)
数据库·mysql
我不会插花弄玉11 小时前
4.数据类型【由浅入深-MySQL】
数据库·mysql
mqiqe11 小时前
AgentScope Java 2.0 协议集成全景解析:A2A、AG-UI、Agent Protocol 三大开放协议实战指南
java·开发语言·ui
脉动数据行情11 小时前
Java 实现台股 TWSE/TPEx 行情采集(个股 + K 线)
java·开发语言·twse·tpex·台股