深分页变慢因数据库需跳过大量数据;推荐游标分页、覆盖索引关联查询、物理分表、归档历史数据、前端限页、缓存预计算等优化方案。
深分页查询变慢,核心原因是数据库要先扫描并跳过前面大量数据,再返回目标页。比如 OFFSET 1000000 LIMIT 20,MySQL 或 PostgreSQL 都得逐行读取前 100 万条记录,即使有索引,也需回表或遍历索引树多次,I/O 和 CPU 开销剧增。
适合按时间、ID 等有序字段排序的场景,不依赖物理偏移量,而是“记住上一页最后一条的值”,下一页直接查大于该值的记录。
cre
ated_at DESC, id DESC 排序,上一页最后一条是 created_at='2025-05-01 10:23:45', id=88721,下一页写法为:SELECT * FROM orders WHERE (created_at, id)
INDEX(created_at, id)),确保能高效定位起始位置当必须用 OFFSET 时,先用覆盖索引快速定位主键,再关联原表取完整字段,避免全字段扫描。
SELECT id, title, content FROM articles ORDER BY create_time DESC LIMIT 100000, 20;
SELECT a.id, a.title, a.content FROM articles a INNER JOIN (SELECT id FROM articles ORDER BY create_time DESC LIMIT 100000, 20) b ON a.id = b.id;
id(假设 id 在索引中),利用索引快速跳过,外层再按 ID 精准回查,大幅减少 I/O如果深分页集中在老数据(如查 3 年前订单的第 1 万页),说明业务逻辑本身不合理——用户极少翻那么深,或数据未及时归档。
orders_archive 表,主表只保留热数据,深分页压力自然下降orders_202501),配合路由规则,让查询落在小表上,OFFSET 成本显著降低对访问频次高、排序固定、更新不频繁的列表(如热门商品榜、排行榜),避免每次实时分页计算。
ZRANGE key start end WITHSCORES 直接取页top_products_page_100),字段含 page_no、item_ids(JSON 数组)、total_count