深分页使用游标后如何支持任意页跳转?
未标记
考查重点:连续翻页与任意定位。游标适合连续翻,任意跳页用锚点/范围定位,精确页码需额外成本
本题目录
参考答案
本答案基于相关资料,由 AI 辅助编写,供学习与面试准备参考。如有疏漏,欢迎反馈指正。
核心回答
普通游标只知道“从上一条记录继续”,不能直接知道第十万页从哪里开始。任意跳页需要额外的位置索引、预计算页锚点或结果快照;若没有这些信息,只能付出跳过前面记录的代价。把 OFFSET 换成 WHERE id > ...,却不知道对应的 id,并没有解决任意跳页。
先根据产品需要选方案:连续浏览用游标;浅层精确跳页可以保留偏移分页;高频深层跳页则用带成本的锚点或物化结果。不能承诺既任意跳页、结果实时不变,又始终是固定低成本。
游标本身怎样保持稳定
例如按 created_at DESC, id DESC 排序,下一页使用上一页末条的两个值:
SELECT id, created_at, amount
FROM seller_bill
WHERE seller_id = :seller
AND (created_at < :last_time
OR (created_at = :last_time AND id < :last_id))
ORDER BY created_at DESC, id DESC
LIMIT :page_size;
需要匹配的索引如 (seller_id, created_at, id)。唯一的 id 打破相同时间的并列关系;不能把页码乘以页大小得到的行序号,直接当作存在且连续的业务 ID。
支持任意定位的几种方式
- 稀疏锚点:缓存某些页起始位置,跳页时找最近锚点,再扫描剩余距离。锚点必须绑定筛选条件、排序和结果版本;数据变化后需要失效或重建。
- 结果快照:先物化符合条件的有序
ID列表或分段位置,再按页读取。适合账单、报表等需要稳定结果的场景,代价是生成、存储与有效期管理。 - 浅分页或受控偏移:限定时间范围和最大页码,必要时先从覆盖索引取出当页
ID再读取详情。这可减少宽行回表,但扫描大量偏移记录的成本仍存在。
只记录创建时间上界,未必冻结状态变化、删除和排序字段更新。要求翻页期间完全一致时,需要明确的快照或版本语义,而不是仅把时间戳编码进游标。
参考资料
- 国内:PingCAP:分页查询:借鉴按排序键划分分页区间和预计算位置的做法,解释页锚点有额外生成成本。
- 国内:阿里邮箱:游标与偏移量分页:采用游标必须继承上次响应的位置这一契约,不能把页码自行换算成游标。
- 国内:JavaGuide:MySQL性能优化规范:采用覆盖索引减少回表、只取所需字段减少读取与传输的机制,解释先取当页标识再读详情能节省什么成本。
- 国内:PingCAP:索引选择:借鉴索引读取与回表的成本区分,解释优化不能只看是否命中索引。
- 国外:MySQL 8.4:LIMIT Query Optimization:核对LIMIT与排序、索引读取之间的关系,区分减少回表和消除偏移扫描。
- 国外:PostgreSQL:LIMIT and OFFSET:采用稳定排序与大偏移仍需计算跳过记录的说明,解释任意跳页并非游标自带能力。
相关面经
1 篇阿里巴巴
AI 全栈开发工程师一面
深分页与卖家账单查询深分页和卖家账单查询的场景,你觉得有哪些要优化的?给订单系统做商家纬度账单查询,order 表分库分表,用卖家来查,近三个月或近六个月,很多条件。首先有深分页问题,深分页怎么优化?第二是这种卖家纬度的查询怎么去支持?(追问·深分页·游标)游标跳页的查询也支持吗?从第一页跳到第五页。(追问·深分页·跳页)账单查询并不像刷抖音一样,有一到十可以选择中间任何一页,你觉得这个方法能用吗?(追问·深分页)跳页怎么办呢?(追问·卖家表)你说卖家表,下单时把买家表落了以后,单独搞一个卖家表落买卖家 id 和买家表业务单号,查的时候查那个卖家表?(追问·卖家表)分页时每页查 200 条,卖家表查 200 个 id,再散到买家库查 n 个库,查 200 次,再聚合?(追问·卖家表)买家的所有字段你都落吗?相当于镜像表一模一样的字段,分表键换了一个?(追问·卖家表)两张表是双写吗?下达时都写上是吧?(追问·卖家表)写入开销小的话,怎么保证事务?A 成功 B 失败怎么办?(分布式事务)
