Seek分页是利用上一页最后记录的排序字段值作为游标直接定位下页起始位置的分页方式;它基于条件连续扫描,避免OFFSET跳过大量数据的性能损耗,响应稳定且支持无状态翻页。

什么是seek分页(游标分页)
Seek分页不是靠OFFSET跳过前N条记录,而是利用上一页最后一条数据的排序字段值作为“游标”,直接定位下一页起始位置。它本质是“基于条件的连续扫描”,避免了偏移量越大越慢的问题。
为什么seek分页比offset更高效
当数据量大、页码靠后时,OFFSET 100000会让数据库先扫描并丢弃前10万行,即使只取20条,I/O和CPU开销也很大。而seek分页通过索引范围查询(如WHERE id > 100000 ORDER BY id LIMIT 20),能直接利用索引定位,响应时间稳定。
- 不依赖跳过行数,性能与页码无关
- 天然支持无状态翻页(适合API分页)
- 避免因并发写入导致的“跳行”或“重复”问题(相比offset+limit)
实现seek分页的关键要求
必须有唯一、非空、有序且可索引的列作为游标字段(常用主键或带唯一约束的时间戳)。若排序依据是多个字段(如ORDER BY status, created_at, id),游标就必须包含全部这些字段,并按相同顺序构造比较条件。
- 推荐使用主键(如
id)——最简单可靠 - 若按时间分页,确保
created_at配合id防重复(因时间可能相同) - 查询必须有对应复合索引,例如
INDEX(status, created_at, id)
典型SQL写法与注意事项
假设要查“status=1”的下一页,上一页最后一条是(status=1, created_at='2024-05-01 10:20:30', id=5000):
SELECT * FROM orders
WHERE status = 1
AND (created_at > '2024-05-01 10:20:30'
OR (created_at = '2024-05-01 10:20:30' AND id > 5000))
ORDER BY created_at, id
LIMIT 20;注意:不能用BETWEEN或IN,必须用逐字段的“大于+等于组合”逻辑来保证全序;游标值需由客户端传回,服务端不做推算。










