MySQL 查询(分页方法的性能差异)

7 阅读2分钟

LIMIT/OFFSET 的性能问题 (O(n²) 复杂度)

使用 LIMIT x OFFSET y 方式分页时,数据库需要:

  1. 扫描并丢弃前 y 条记录
  2. 再返回接下来的 x 条记录

为什么是 O(n²) 复杂度

  • 随着页码增加,OFFSET 值变大
  • 数据库需要读取更多记录才能返回结果
  • 例如:获取第50页(每页10条)时,数据库需要读取500条记录,但只返回10条
  • 当用户浏览多个页面时,累计读取的记录数呈二次方增长

书签扫描方式 (O(n) 复杂度)

书签扫描方式使用上一页最后一条记录的唯一标识作为"书签",查询时直接从这个位置开始:

-- 假设id是主键,且按id排序
-- 第一页
SELECT * FROM table ORDER BY id LIMIT 10;
​
-- 后续页面(假设上一页最后一条记录id为123)
SELECT * FROM table WHERE id > 123 ORDER BY id LIMIT 10;

优势

  1. 不再需要跳过大量记录
  2. 每次查询复杂度为 O(1),总体复杂度为 O(n)
  3. 查询效率不受页码大小影响
  4. 能有效利用索引

实际例子

假设要获取用户表中的第100页,每页20条记录:

传统方式

SELECT * FROM users ORDER BY id LIMIT 20 OFFSET 1980;

数据库需要读取1,980+20条记录,但只返回20条。

书签方式

-- 假设上一页最后一个用户id是2468
SELECT * FROM users WHERE id > 2468 ORDER BY id LIMIT 20;

数据库直接定位到id>2468的位置,只读取需要的20条记录。

注意事项

书签分页要求:

  1. 必须有唯一且有序的字段作为书签
  2. 前端需要记录当前页的最后一个书签值
  3. 适用于单向浏览的场景(向前翻页)

当需求包括随机访问页码时,可能需要结合两种方法或使用其他策略。