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

张开发
2026/5/12 15:40:23 15 分钟阅读

分享文章

求解深分页问题,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;快直接从 ID1000000 处开始扫描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 的局限性不适合的情况不适合“跳页”查询如果你要求用户能直接点击“第 500 页”这种方案就瞎了。因为你没法在不扫描的情况下知道第 499 页的最后一个 ID 是多少。主键必须有序或排序字段稳定如果数据频繁删除导致 ID 极其不连续虽然不影响性能但在某些需要精确计算步长的业务场景下可能会有小麻烦。4. 补充如果必须要“跳页”怎么办如果业务强制要求深分页且必须支持跳页通常有两种折中方案方案一延迟关联Deferred Join先通过覆盖索引只查找主键减少回表。SELECT*FROMtablet1INNERJOIN(SELECTidFROMtableWHERE...LIMIT1000000,10)t2ONt1.idt2.id;在二级索引树里面遍历索引树找id,跳过签100万个id返回10个id,然后10个id再联表查询原理在内查询里只走索引不回表等确定了这 10 个 ID 后再回表效率提升巨大。方案二限制最大翻页数这也是大厂常用的办法如百度、谷歌、京东。你会发现它们通常只让你翻到 100 页左右后面的数据就不给看了。总结last pk 是解决深分页性能问题的“银弹”但它牺牲了“自由跳页”的功能。如果你的场景是瀑布流、滚动加载或批量数据处理请务必使用last pk方案。你现在的业务场景是属于用户侧的列表展示还是后台的数据处理任务

更多文章