首页 >> 基础教程

mysql分页问题

        MySQL 的分页问题通常表现为 数据量较大时,使用 LIMIT offset, rows 方式分页性能急剧下降,尤其是当 offset 值非常大时(如第 1000 页)。

一、问题根源:OFFSET 的工作原理

  1. 低效的扫描过程:

    • SELECT ... LIMIT 100000, 20 并不是直接跳到第 100000 条记录。

    • MySQL 需要先 扫描前 100000 + 20 条记录,然后丢弃前 100000 条,只返回最后的 20 条。

    • OFFSET 越大,需要扫描和丢弃的数据就越多,性能越差(时间复杂度接近 O(n))。

  2. 额外开销:

    • 大 OFFSET 会导致大量无效的磁盘 I/O 和 CPU 消耗。

    • 如果查询包含 ORDER BY,还需对所有满足条件的数据进行排序(可能用到临时表或文件排序)。

二、核心优化方案

  1. 延迟关联(Deferred Join)— 最推荐

    1. 先通过子查询快速定位到主键 ID,再用主键关联回原表获取完整数据。避免对大结果集排序和扫描。

      SELECT t1.*
      FROM your_table t1
      JOIN (
          SELECT id -- 只查询主键
          FROM your_table    WHERE ... -- 可选:查询条件
          ORDER BY create_time DESC -- 排序字段
          LIMIT 100000, 20 -- 分页参数) t2 ON t1.id = t2.id; -- 通过主键关联ORDER BY t1.create_time DESC; -- 保持排序
    2. 子查询只需扫描索引(覆盖索引最佳),避免回表。

    3. 外层查询仅需 20 次主键回表,效率极高。

    4. 适合单表或多表关联时对大表分页。

  2. 游标分页(Cursor-based Pagination)

    1.  用上一页最后一条记录的有序唯一值(如自增 ID、时间戳)作为起点,替代 OFFSET

    2. -- 第一页(按时间倒序)
      SELECT *
      FROM your_table
      WHERE ... -- 查询条件
      ORDER BY create_time DESC, id DESC -- 排序(确保唯一性)
      LIMIT 20;
      
      -- 下一页(假设上一页最后一条记录的 create_time='2023-10-01 12:00:00', id=100)
      SELECT *
      FROM your_table
      WHERE (create_time < '2023-10-01 12:00:00') 
         OR (create_time = '2023-10-01 12:00:00' AND id < 100) -- 处理相同时间的情况
         ORDER BY create_time DESC, id DESCLIMIT 20;
    3. 优势:

      1. 性能稳定(O(1)),不受页码影响。

      2. 无 OFFSET,直接通过索引定位起点。

    4. 限制:

      1. 只能顺序翻页(上一页/下一页),不能跳页。

      2. 排序字段必须唯一且有序(可组合多个字段)。

  3. 覆盖索引(Covering Index)

    1. -- 创建覆盖索引(包含查询字段和排序字段)
      ALTER TABLE your_table ADD INDEX idx_cover (status, create_time, id, name, title);
      -- 查询直接走索引
      SELECT id, name, title -- 只查询索引包含的字段
      FROM your_table
      WHERE status = 1
      ORDER BY create_time DESC
      LIMIT 100000, 20;
    2. 优势:

      1. 无需回表,性能显著提升。

      2. 适合查询字段固定的场景。

    3. 限制:

      1. 索引可能较大,占用存储。

      2. 无法解决 OFFSET 扫描问题(仍需优化为大表方案 1)。


场景推荐方案
深度分页(如第 1000 页)✅ 延迟关联(方案 1)
无限滚动(如新闻流)✅ 游标分页(方案 2)
固定条件筛选+分页✅ 覆盖索引(方案 3)
需要跳页(如第 1 页→第 5 页)⚠️ 延迟关联 + 业务层妥协

上面的都不能解决这个问题的时候可以考虑其它数据存储方案



最新文章
mysql分页问题2025-08-04
千万数据先insert和先建索引哪个快2025-08-04
MySQL 中大小表关联查询如何优化2025-08-04
sql技巧-每个班年龄排前两名的人2025-08-03
MySQL 导致 cpu 飙升的话,要怎么处理呢?2025-07-29
MySQL 中为千万级大表添加字段2025-07-29
mysql中百万级别以上的数据如何删除2025-07-29
分库分表带来的问题2025-07-29
mysql中常用的分库分表中间件有哪些2025-07-29
mysql不停机扩容2025-07-29
备案号:蜀ICP备2023042032号-1