来源:markus-winand · 原文
核心问题
很多列表页、消息流和搜索页并不需要全量结果,只需要前几条。问题在于,如果数据库必须先排序完全部结果,前几条也会变得很贵。
这一章的答案
作者把高效分页建立在 pipelined order by 之上:先确保索引能按需要的顺序吐出结果,再只取前 N 条。
Offset 的问题
offset 最大的问题是它经常仍要从头数过去,因此:
- 页码越深越慢;
- 新数据插入后,页内容容易漂移;
- 本质上没有真正“跳过”前面那些行。
Seek Method
更优方案通常是 seek pagination:
- 记住上一页最后一行的排序键;
- 下一页用这个键作为新的范围边界;
- 让数据库从该位置继续扫描。
这样分页就从“跳过很多行”变成了“从一个已知边界继续查找”,也就是索引擅长的问题。
一个关键提醒
稳定分页依赖确定性排序。如果 order by 不能唯一确定行顺序,就必须补 tie-breaker 列,并让索引顺序与之对齐。
相关页面:use-the-index-luke · index-supported-sorting-and-pagination · query-shape-and-index-usage · sql-indexing