← 每日面试题 学习看板

分库分表后如何进行分页查询?

面试题/03数据库中间件/04分库分表/分库分表后如何进行分页查询?.md

面试记录 2026-09-23

题目:分库分表后如何进行分页查询?

难度:medium

标签:db/sharding, general/knowledge, difficulty/medium

评分:⭐⭐⭐☆☆(3/5)

我的回答

分库分表后的分页,这时候就看分页业务的指标,只用什么分页了,基本上是用时间。这时候是首先业务分表的规则,如果是时间性质的,直接它对应的去做分表就可以了。然后每次查询的时候携带的它的条件做划分。另外直接可能就用三方组件,把这些分表的分表后的数据存到 ES 或者是 Clickhouse 中,直接去在数仓这些东西里边去查数据,而不是再去数据库分库去做分页查询。再有就是使用业务组件查出对应的 ID,然后异构的去批量地查一页的数据里边的指向信息,调远程服务,然后获取数据的详情信息。

点评

优点:

不足:

补充:

完整讲解

第一部分:知识重点剖析

核心考点定位:能否识别分页的分片放大问题,并给出深分页的四种主流解。

知识点拆解:

  1. 分片后分页的三个难点:
  1. 深分页(Deep Pagination)问题本质:
  1. 分片中间件的分页执行流程:
  1. 四种主流解决方案:
  1. 分片键设计对分页的影响:
  1. 典型业务组合:

第二部分:考察方向与延伸递进

考察方向:

延伸递进面试题:

  1. LIMIT 100000,10 在 MySQL 里为什么慢?
  1. 游标分页的劣势是什么?哪些场景不适合?
  1. 分片中间件做全局分页时如何优化?(如 ShardingSphere)

第三部分:面试者参考回答(300-600 字口语化)

面试官您好,分库分表后的分页有两个层面的问题:一是分片带来的分散查询,二是深分页本身的代价放大。我分开讲。

先说分片本身的难点。一页 10 条数据可能分散在 N 个分片,中间件要做三步归并:

  1. 向每个分片发 SELECT * FROM t ORDER BY x LIMIT 0, offset+size
  2. 所有分片返回后内存排序
  3. 截断前 offset 行返回后 size 行

代价是 N 个分片 × 单库深分页耗时,如果单库深分页 500ms,8 个分片就要 4 秒。这是分片场景最痛的地方。

然后是深分页(Deep Pagination)本身。LIMIT 100000, 10 在 MySQL 里要扫 100010 行,前 100000 行读回后丢弃。这在单库 100w 行的表就已经几秒,分片场景还要乘以分片数。所以深分页是分片后必须治的病。

四种主流解:

第一:游标分页(Keyset Pagination)——这是最优雅的方案。用上一页最大的 ID 作为下一页起点:WHERE id < :last_id ORDER BY id DESC LIMIT 10。因为走了主键索引或排序索引,每次都是恒定性能,无论翻到多少页都不变慢。适合 Feed 流、聊天记录这类"无限滚动"的场景。缺点是不能跳页、不能显示总页数——搜索场景就不适合。

第二:延迟关联。两步查询:先 SELECT id FROM t ORDER BY create_time LIMIT 100000,10 走覆盖索引(不查主表),再 SELECT * FROM t WHERE id IN (...) 回表拿详情。第一步虽然扫了 100010 行索引,但索引比主表小 10 倍,性能改善明显。适合能接受一定 offset 但想优化深分页的场景。

第三:限制翻页深度。这个方案最粗暴但最实用——业务侧直接禁止翻到 100 页后,或者 20 页后引导用户走搜索框。因为 99% 的用户不会翻到 20 页以外,这个成本远低于架构改造。我在项目里就用过,直接把最大翻页限制在 50 页,配合搜索框兜底,效果非常好。

第四:ES / ClickHouse。把分片后的数据异步同步到 ES 或 OLAP 库,主库只存详情,排序和分页全部走 ES。ES 有 search_after 天然支持游标分页。代价是数据同步延迟(通常秒级),但换来的是查询性能提升 10-100 倍。适合后台管理、报表这类对实时性不敏感的场景。

分片键设计对分页也有影响。如果按时间分片,且按时间排序,那"最新数据"天然在最新分片,分页只需查最新分片——代价最低。如果按 hash 分片但按时间排序,就要跨全部分片扫描——代价最大。所以设计分片键时,排序字段尽量和分片键对齐。

电商订单列表的典型组合:

一句话总结:能游标就游标,不能游标就限制翻页深度,实在不行走 ES——顺序永远是这样。深分页是分片场景的分页杀手,一定要在设计阶段就规避。