news 2026/6/10 15:19:44

3 个奇淫巧技,分库分表 LIMIT 翻页性能直接拉满!

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
3 个奇淫巧技,分库分表 LIMIT 翻页性能直接拉满!

线上出了个离谱问题:运营同学在后台导出近 3 个月订单时,点击分页到第 100 页,直接把数据库查崩了。排查后发现,代码里写了LIMIT 9900, 100,在分库分表场景下,这行 SQL 相当于让 8 个分片各查 1 万条数据,再拉到应用层内存排序,直接把内存溢出了。

其实分库分表的分页查询,藏着很多反常识的奇技淫巧,但这些技巧都有严格的适用边界,用错了反而会埋坑。我来分享 3 个实战中验证过的骚操作。

分库分表 LIMIT 是性能杀手

单表分页用LIMIT offset, size没问题,但分库分表后,数据散在多个分片里,比如你要查LIMIT 10000, 10(第 1001 页),会发生两件离谱的事:

全分片扫描:每个分片都要执行LIMIT 0, 10010(因为不知道其他分片的数据分布,只能把前 10010 条都查出来,避免漏数据);

内存爆炸排序:假设 8 个分片,每个返回 10010 条,共 8 万多条数据,全拉到应用层排序,再截取第 10000-10010 条。内存和 CPU 直接飙红,我之前见过最夸张的案例,offset=100000时,一个分页请求耗时 12 秒,直接触发服务熔断。

所以我们下边要讲的都是绕开全分片扫描 + 内存排序,但每个方案的适用场景天差地别,核心原则:不盲目追高性能,先看业务场景是否匹配

锚点分页

锚点分页,性能最优,但仅限加载更多场景。

这是我最常用的技巧,核心思路是用数据本身的有序字段当锚点,替代 offset,比如按自增 ID 或时间戳分页。但注意:不是所有有序字段都能用,必须满足分片内 + 分片间都有序

按 ID 范围分片

假设订单表按 ID 范围分 3 个分片:

  • 分片 1:ID 1-10000(分片内有序,且小于分片 2 的 ID);

  • 分片 2:ID 10001-20000(同理);

  • 分片 3:ID 20001-30000(同理);

要查第 2 页(10 条 / 页),步骤如下:

  1. 查第 1 页时:执行ORDER BY id DESC LIMIT 10,拿到最后一条数据的 ID 是last_id=100(这个 ID 就是锚点);

  2. 查第 2 页时:直接用WHERE id < 100 ORDER BY id DESC LIMIT 10

  3. 查第 3 页时:再用第 2 页最后一条的 ID(比如 90)当锚点,执行WHERE id < 90 ORDER BY id DESC LIMIT 10

为什么性能高?

每个分片都能独立执行WHERE id < xxx LIMIT 10,只返回 10 条数据(不用查前 N 条)。比如查第 1001 页,每个分片也只返回 10 条,汇总后排序取 10 条,网络和内存开销直接降为原来的 1/1000。

必避的 2 个坑:

  1. 别用哈希分片:如果按ID mod 3哈希分片,分片 1 的 ID 可能是 3、6、9...,分片 2 是 1、4、7...,此时 ID 全局有序但分片内无序,执行WHERE id < 100仍需全量扫描分片内数据,退化为 “内存聚合”;

  2. 不支持跳页:只加载更多(下一页依赖上一页的锚点),无法直接从第 1 页跳到第 100 页。但可以通过产品设计规避,比如抖音、小红书的列表都是加载更多,用户体验反而更好。

分片标记法

刚才的锚点分页不支持跳页,但有些场景比如后台管理系统,又必须要跳页,怎么办?我之前在电商后台做订单导出时,用过分片标记法,核心是给每个库、表记录数据范围和总量,快速定位目标页在哪个分片。

分片标记法支持跳页,但必须控制元数据一致性。

用法示例

假设订单表按用户 ID 范围分 2 库,每库按时间分 12 表(如库 1 - 表 202401、库 1 - 表 202402...),先在 Redis 里维护 库、表级别的元数据:

库 - 表

起始 ID

结束 ID

数据总量

库 1 - 表 202401

1

5000

5000

库 1 - 表 202402

5001

12000

7000

库 2 - 表 202401

12001

18000

6000

....

....

..18000

6000

现在要查LIMIT 15000, 10(第 1501 页),步骤如下:

  1. 查元数据定位库、表:计算累计数据量,库 1 - 表 202401(5000)+ 库 1 - 表 202402(7000)= 12000 <15000,再加上库 2 - 表 202401 的 6000,累计 18000>15000,所以目标在库 2 - 表 202401;

  2. 计算表内偏移量:表内偏移量 = 15000 - 12000 = 3000,所以库 2 - 表 202401 执行LIMIT 3000, 10

  3. 直接返回结果:因为库、表按 ID 有序,查询结果就是全局第 15000-15010 条,不用汇总其他分片。

必避的 2 个坑:

1.元数据必须实时但不能强同步

数据新增、删除时,要同步更新 Redis 元数据,但高并发下不能加分布式锁(会卡住业务),建议用定时 + 增量日志:每 5 分钟全量统计一次,同时记录增量(如新增 100 条、删除 10 条),查询时叠加增量;

若允许最终一致性(如后台查询允许误差 10 条),这个方案很稳;若要强一致,只能放弃跳页,用锚点分页;

2.不支持非分片键排序:如果要按支付时间排序(分片键是用户 ID),支付时间在 “库 - 表” 内无序,元数据无法定位,仍需全分片扫描。

反向分页

反向分页,仅适用于查最后 1 页,别乱用

这个技巧最反常识,但局限性也最大。如果要查最后几页数据(比如用户查最早的订单),用普通分页会查LIMIT 9990, 10,但可以反向查,避开大 offset。

仅查最后 1 页

假设订单表按 ID 范围分片,总数据量 10000 条(1000 页,10 条 / 页),要查最后 1 页(ID 9991-10000):

  1. 反向查锚点:执行ORDER BY id ASC LIMIT 10,拿到最前面 10 条的 ID(1-10),取最大 ID 作为反向锚点(10);

  2. 查最后 1 页:执行WHERE id > 10 ORDER BY id DESC LIMIT 10,拿到的就是 ID 10000-9991(最后 10 条);

  3. 调整顺序:如果需要正序展示,把结果再倒过来即可。

为什么能生效?

因为LIMIT 0, 10LIMIT 9990, 10快 100 倍. 每个分片查前 10 条数据,汇总后取最大的 10 个 ID 作为锚点,再查大于锚点的数据,避免了大 offset 扫描。

必避的 2 个坑:

  1. 仅适用于最后 1 页:如果要查倒数第 10 页(第 991 页),按这个逻辑无法定位锚点(需要知道第 9900 条数据的 ID),只能查倒数第 1 页;

  2. 数据不能有大量删除:如果中间有大量 ID 被删除(如 ID 5000-8000 都被删了),总数据量变为 7000 条,此时WHERE id >10 ORDER BY id DESC LIMIT10拿到的是 7000-6991(正确),但如果删除的是最后 100 条(ID 9901-10000),总数据量变为 9900 条,需要重新计算反向锚点,增加复杂度。

说在后边

其实分库分表分页的核心不是炫技,而是在业务和技术之间找平衡。能通过产品设计规避跳页(用加载更多),就优先用锚点分页(性能最优),必须跳页就用分片标记法(接受最终一致性);实在没办法才考虑中间件(如ShardingSphere的全局排序)。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/9 13:25:07

Lowcoder_CN终极指南:开源低代码开发平台深度解析与高效使用

Lowcoder_CN终极指南&#xff1a;开源低代码开发平台深度解析与高效使用 【免费下载链接】lowcoder_CN &#x1f525;&#x1f525;&#x1f525;开源Retool, Tooljet和Appsmith的替代方案&#xff0c;码匠的开源版 项目地址: https://gitcode.com/gh_mirrors/lo/lowcoder_CN…

作者头像 李华
网站建设 2026/6/10 14:39:04

OpenCode完整指南:AI编程助手的革命性工作流

OpenCode完整指南&#xff1a;AI编程助手的革命性工作流 【免费下载链接】opencode 一个专为终端打造的开源AI编程助手&#xff0c;模型灵活可选&#xff0c;可远程驱动。 项目地址: https://gitcode.com/GitHub_Trending/openc/opencode OpenCode是一款专为现代开发者打…

作者头像 李华
网站建设 2026/6/7 9:12:39

Langchain-Chatchat在科研文献检索中的创新应用

Langchain-Chatchat在科研文献检索中的创新应用 在当今科研竞争日益激烈的环境下&#xff0c;研究人员每天都要面对海量的学术论文、项目报告和实验记录。如何从这些堆积如山的PDF和文档中快速提取关键信息&#xff0c;已成为制约研究效率的一大瓶颈。传统的关键词搜索往往只能…

作者头像 李华
网站建设 2026/6/10 13:03:42

AR.js实战指南:30分钟构建跨平台Web增强现实应用

AR.js实战指南&#xff1a;30分钟构建跨平台Web增强现实应用 【免费下载链接】AR.js Efficient Augmented Reality for the Web - 60fps on mobile! 项目地址: https://gitcode.com/gh_mirrors/ar/AR.js Web增强现实技术正在改变我们与数字世界交互的方式&#xff0c;而…

作者头像 李华
网站建设 2026/6/8 13:16:50

Figma组件库终极解决方案:打造shadcn/ui设计开发一体化工作流

面对shadcn/ui组件开发中设计与实现脱节的效率瓶颈&#xff0c;awesome-shadcn-ui项目提供了完整的Figma组件库资源&#xff0c;实现设计到代码的无缝转换。通过精选的组件库集合&#xff0c;前端开发者和UI设计师能够建立统一的设计语言&#xff0c;从根本上提升项目协作效率。…

作者头像 李华
网站建设 2026/6/9 3:47:43

Langchain-Chatchat结合大模型Token计费系统的联动设计

Langchain-Chatchat 与大模型 Token 计费系统的联动设计 在企业纷纷拥抱 AI 的今天&#xff0c;一个看似智能的问答系统背后&#xff0c;可能正悄悄吞噬着惊人的算力成本。你有没有遇到过这样的场景&#xff1a;客服团队频繁调用大模型生成回复&#xff0c;月底账单却远超预算&…

作者头像 李华