news 2026/4/23 7:28:10

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/4/23 9:53:26

智能调校新体验:xManager如何让手机流畅如初

智能调校新体验&#xff1a;xManager如何让手机流畅如初 【免费下载链接】xManager Ad-Free, New Features & Freedom 项目地址: https://gitcode.com/GitHub_Trending/xm/xManager 还记得上次玩游戏时突然卡顿的尴尬吗&#xff1f;或是电量仅剩20%却还要坚持使用手…

作者头像 李华
网站建设 2026/4/23 12:53:50

3大实战策略:Windows系统上AMD显卡的PyTorch部署指南

你刚拿到AMD Radeon显卡&#xff0c;想在Windows 11系统上运行PyTorch进行深度学习训练&#xff0c;却发现官方文档指向WSL方案&#xff1f;别担心&#xff0c;这正是当前技术生态的真实写照。本文将为你揭示在HIP SDK环境下实现AMD显卡与PyTorch协同工作的完整解决方案。 【免…

作者头像 李华
网站建设 2026/4/23 12:34:00

ControlNet++终极指南:掌握多条件AI图像生成的艺术

还在为AI生成的图像无法准确表达你的创意而烦恼吗&#xff1f;想要同时控制人物姿势、场景深度和艺术风格却找不到合适的工具&#xff1f;ControlNet正是为你量身打造的智能绘图解决方案&#xff0c;它通过多条件控制技术让AI图像生成变得前所未有的精准和灵活。 【免费下载链接…

作者头像 李华
网站建设 2026/4/23 13:18:48

版本冲突导致项目停滞?Open-AutoGLM不兼容问题速解手册

第一章&#xff1a;版本冲突导致项目停滞&#xff1f;Open-AutoGLM不兼容问题速解手册在集成 Open-AutoGLM 到现有 NLP 流水线时&#xff0c;开发者常因依赖版本不匹配遭遇运行时异常&#xff0c;典型表现为模块导入失败或推理结果异常。此类问题多源于 PyTorch、Transformers …

作者头像 李华
网站建设 2026/4/23 11:35:14

PowerJob Python任务开发实战:轻松实现跨语言分布式调度

PowerJob Python任务开发实战&#xff1a;轻松实现跨语言分布式调度 【免费下载链接】PowerJob 项目地址: https://gitcode.com/gh_mirrors/pow/PowerJob 你是不是曾经遇到过这样的困扰&#xff1f;在一个复杂的分布式系统中&#xff0c;Java应用需要调度Python脚本执行…

作者头像 李华
网站建设 2026/4/23 11:22:41

Nextcloud API文档终极指南:从零掌握云服务接口开发

Nextcloud API文档终极指南&#xff1a;从零掌握云服务接口开发 【免费下载链接】server ☁️ Nextcloud server, a safe home for all your data 项目地址: https://gitcode.com/GitHub_Trending/se/server 想要快速上手Nextcloud云服务的API开发&#xff1f;作为一款强…

作者头像 李华