分库分表怎么分页?维护一个全局主键表可行吗?
📌 分库分表怎么分页?维护一个全局主键表可行吗?
分库分表后,传统的 MySQL 分页方式会失效,因为数据已经分散到多个库和多个表中。实际项目中通常采用:
- 基于全局唯一ID分页(推荐)
- ES搜索分页
- 中间件聚合分页(ShardingSphere)
- 业务维度分页
1️⃣ 问题背景
当系统数据量达到千万级甚至亿级以后,单表查询性能开始下降。
例如订单系统:
数据量:10亿条
此时通常会进行分库分表:
order_1
order_2
...
order_63
甚至:
db1.order_16~31
db2.order_32~47
db3.order_48~63
此时出现一个非常经典的问题:
SELECT * FROM order LIMIT 0,20;
已经无法执行。
2️⃣ 核心原理
为什么传统分页失效?
在单表时代:
FROM order_info
ORDER BY id DESC
LIMIT 0,20;
数据库只扫描一张表即可。
而分库分表后:
db0.order_1
...
db3.order_63
数据分布在64张表中。
如果还想获取前20条数据:
- 每张表先查20条
- 64张表共返回1280条
- 应用层排序
- 取最终20条
这就是所谓的:
3️⃣ 数据结构分析
订单表结构
id BIGINT PRIMARY KEY,
user_id BIGINT,
amount DECIMAL(10,2),
create_time DATETIME
);
按照订单ID进行分片:
例如:
- 1001 → order_41
- 1002 → order_42
- 1003 → order_43
数据被打散存储。
4️⃣ 算法分析
方案一:全量聚合分页
最简单但性能最差。
↓
结果汇总
↓
排序
↓
分页
时间复杂度:
数据量大时无法接受。
方案二:基于ID游标分页(推荐)
解决了深分页问题,依旧需要聚合。
互联网公司最常见方案。
第一次查询:
FROM order_info
WHERE id <= MAX_ID
ORDER BY id DESC
LIMIT 20;
返回最后一条记录:
下一页:
FROM order_info
WHERE id < 9856321
ORDER BY id DESC
LIMIT 20;
这种方式不需要offset。
方案三:ES分页
如果需要复杂查询:
- 订单搜索
- 商品搜索
- 日志查询
通常同步数据到ES。
分页由Elasticsearch完成。
5️⃣ 执行流程
基于全局ID分页流程
↓
查询各分片前20条数据
↓
应用层归并排序
↓
返回20条结果
↓
记录最后一个ID(lastId)
↓
用户请求下一页
↓
WHERE id < lastId
↓
继续查询
全局ID生成流程
↓
获取全局唯一ID
↓
根据ID计算分片
↓
写入对应库表
6️⃣ 实际案例
方案一:全局主键表
很多同学首先想到:
id BIGINT AUTO_INCREMENT PRIMARY KEY
);
获取主键:
SELECT LAST_INSERT_ID();
这样确实可以生成唯一ID。
但是有明显问题:
- 单点故障
- 数据库压力集中
- 高并发下性能差
- 扩展性不足
方案二:Snowflake雪花算法
目前最主流方案。
生成64位Long类型ID。
特点:
- 全局唯一
- 趋势递增
- 无需数据库
- 支持分布式部署
例如:
根据ID直接分片:
7️⃣ 优缺点分析
| 方案 | 优点 | 缺点 |
|---|---|---|
| 全局主键表 | 简单 | 单点瓶颈 |
| UUID | 全局唯一 | 索引离散 |
| Redis自增 | 性能高 | 依赖Redis |
| Snowflake | 高性能、分布式 | 时钟回拨问题 |
8️⃣ 面试常见问题
Q1:分库分表后还能使用 limit 分页吗?
可以,但需要所有分片查询后再聚合排序,性能较差。
Q2:为什么推荐游标分页?
避免深度分页导致大量数据扫描,性能稳定。
Q3:维护一个全局主键表可以吗?
理论上可以,但并发量大时会成为瓶颈,因此生产环境很少使用。
Q4:互联网公司一般怎么生成主键?
Snowflake雪花算法、Leaf、美团Leaf、百度UidGenerator等。
Q5:订单列表分页怎么做?
优先按照用户维度分片,然后采用ID游标分页。
Q5:如何记录lastId
{
"list":[
{"id":100},
{"id":99},
{"id":98}
],
"nextCursor":98
}
9️⃣ 总结
📌 分库分表最大的难点不是分片,而是分页、排序和统计。
📌 全局主键表可以生成唯一ID,但无法解决分页问题,并且存在单点瓶颈。
📌 当前主流方案是 Snowflake + 分片键路由 + 游标分页。
📌 深度分页场景优先考虑 ES 搜索分页或基于ID的游标分页,而不是传统 limit offset 分页。
📌 面试中如果被问到“分库分表怎么分页”,最佳回答通常是:ShardingSphere聚合分页 + 游标分页 + Snowflake全局ID。
相关文章
-
Redis持久化机制详解:RDB与AOF原理、实现流程与生产实践
Redis持久化机制详解:RDB与AOF原理、实现流程与生产实践
NEW个对象 2026-06-12
-
如何设计一个亿级系统?
如何设计一个亿级用户系统?
NEW个对象 2026-06-11
-
AI 自动化研发 Prompt 流程设计
如果按照标准化研发流程推进,建议将 Prompt 固化为多个阶段,而不是每次重新编写。 通过将需求分析、数据库设计、代码生成、代码审查和自动测试拆分为独立阶段,可以形成完整的 AI 自动化研发链路。
NEW个对象 2026-06-12