告别慢 SQL:MySQL 百万级数据深分页优化策略

在后台管理系统中,“分页查询”是标配。但当数据量达到百万级时,你是否遇到过 LIMIT 1000000, 10 查不出来或者执行需要几秒钟的情况?

这就是经典的 Deep Pagination(深分页) 问题。

1. 为什么深分页这么慢?

看下面这条 SQL:

SELECT * FROM t_order ORDER BY id LIMIT 1000000, 10;

你以为 MySQL 是跳过前 100万条,直接取 10 条?

错!

MySQL 的执行逻辑是:

  1. 扫描满足条件的 1000010 行数据。
  2. 抛弃前面的 1000000 行。
  3. 返回最后的 10 行。

这不仅浪费了大量的 IO,如果是 SELECT *,还会因为回表(Back to Table)导致性能进一步恶化。

2. 解决方案 A:延迟关联(覆盖索引优化)

利用覆盖索引先查出主键 ID,再跟原表做 JOIN。因为查 ID 只需要扫描索引树,速度极快。

优化后 SQL:

SELECT t1.* 
FROM t_order t1
INNER JOIN (
    -- 这里只查 ID,利用覆盖索引,不回表
    SELECT id FROM t_order ORDER BY id LIMIT 1000000, 10
) t2 ON t1.id = t2.id;

效果:通常能将几秒的查询优化到几百毫秒。

3. 解决方案 B:游标法(Seek Method)

如果你能拿到上一页最后一条数据的 ID(last_id),并且 ID 是连续或单调递增的,可以直接用 WHERE 过滤。

优化后 SQL:

-- 假设上一页最后一条 ID 是 1000000
SELECT * FROM t_order 
WHERE id > 1000000 
ORDER BY id ASC 
LIMIT 10;

效果:无论翻到第几页,性能都是 O(1) 的,毫秒级响应。
缺点:只能点“下一页”,不能直接跳转到第 N 页(但在移动端 Feeds 流场景非常适用)。

总结

  • 普通分页(前几页):直接 LIMIT
  • 管理后台深分页(跳页):用延迟关联。
  • App 瀑布流(无限滚动):用游标法 (WHERE id > ?)。
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐