MySQL超大分页如何解决?

文章目录

  • [一、为什么 `LIMIT offset, size` 会慢到怀疑人生?](#一、为什么 LIMIT offset, size 会慢到怀疑人生?)
  • 二、解决思路总览(先看地图)
  • [三、王者方案:游标分页(Keyset Pagination)](#三、王者方案:游标分页(Keyset Pagination))
      • [1️⃣ SQL 示例(最推荐)](#1️⃣ SQL 示例(最推荐))
      • [2️⃣ 前端交互方式](#2️⃣ 前端交互方式)
      • [3️⃣ 优点](#3️⃣ 优点)
      • [4️⃣ 缺点](#4️⃣ 缺点)
    • 四、必须支持"跳页"?那就用覆盖索引
      • [1️⃣ 错误写法(慢)](#1️⃣ 错误写法(慢))
      • [2️⃣ 正确写法(两步走)](#2️⃣ 正确写法(两步走))
      • [3️⃣ 进一步优化(覆盖索引)](#3️⃣ 进一步优化(覆盖索引))

一、为什么 LIMIT offset, size 会慢到怀疑人生?

sql 复制代码
SELECT * FROM orders
ORDER BY id
LIMIT 1000000, 20;

MySQL 的真实工作流程不是"直接跳到第 100 万条",而是:

  1. 从第一行开始扫描

  2. 丢掉前 1,000,000 行

  3. 再取 20 行

👉 offset 越大,丢的数据越多

👉 即使有索引,也要一路扫过去

所以:
超大分页 = 扫描 + 丢弃 + 心态爆炸


二、解决思路总览(先看地图)

方案 适合场景 性能
游标分页(Keyset) 列表 / 无限滚动 ⭐⭐⭐⭐⭐
子查询 + 覆盖索引 必须跳页 ⭐⭐⭐⭐
记录最大页数 后台系统 ⭐⭐⭐
ES / Redis 搜索 / 复杂排序 ⭐⭐⭐⭐⭐

三、王者方案:游标分页(Keyset Pagination)

核心思想 :

👉 不要告诉数据库"我要第几页"

👉 告诉它"我要上一页最后一条之后的数据"

1️⃣ SQL 示例(最推荐)

sql 复制代码
SELECT *
FROM orders
WHERE id > 1000000
ORDER BY id
LIMIT 20;
  • id 必须是递增、有索引

  • 前端传 lastId,而不是 page

2️⃣ 前端交互方式

  • 第一次:不传 lastId

  • 下一页:传上一次返回的 lastId

sql 复制代码
{
  "lastId": 1000000,
  "pageSize": 20
}

3️⃣ 优点

  • 🚀 性能稳定,和第几页无关

  • 🚫 不扫描无用数据

  • ✅ MySQL 最擅长这种查询

4️⃣ 缺点

  • ❌ 不能随意跳到第 100 页

  • ❌ 不适合"精确页码"的产品经理审美

📌 结论:

这是阿里、字节、美团后台列表的常规操作


四、必须支持"跳页"?那就用覆盖索引

如果产品经理坚持要"跳到第 500 页",那只能降低伤害。

1️⃣ 错误写法(慢)

sql 复制代码
SELECT *
FROM orders
ORDER BY id
LIMIT 1000000, 20;

2️⃣ 正确写法(两步走)

sql 复制代码
SELECT *
FROM orders
WHERE id >= (
    SELECT id
    FROM orders
    ORDER BY id
    LIMIT 1000000, 1
)
ORDER BY id
LIMIT 20;

3️⃣ 进一步优化(覆盖索引)

sql 复制代码
SELECT o.*
FROM orders o
JOIN (
    SELECT id
    FROM orders
    ORDER BY id
    LIMIT 1000000, 20
) t ON o.id = t.id;
  • 子查询只扫索引

  • 回表次数极少

📌 注意 :

offset 再大也只是"相对能忍",不是本质解决


相关推荐
JavaEdge.12 分钟前
设定索引方法和检索设置
数据库
小蒜学长15 分钟前
基于Vue.js + Spring Boot的酒店客房预订系统设计与实现(代码+数据库+LW)
java·数据库·spring boot·后端·酒店客房预订系统
墨者阳16 分钟前
KingbaseES V9R2C16 深度实测:64位事务ID、内存防护、集群备份与坏块修复四大能力全解析
数据库
事圆则缓22 分钟前
聊天与引用回复的 SQL 怎么设计
数据库·sql
APItesterCris23 分钟前
告别反复手工查价:用 Open‑Claw 搭建商品监控与数据分析小工具
大数据·数据库·数据仓库·自动化
来福猿27 分钟前
分布式锁 Redis 实现源码分析:SETNX、过期时间与可重入设计
数据库·redis·分布式
xiangyun6132 分钟前
C++ list 模拟实现(一):手撕双向链表,从节点到迭代器
数据库·c++·算法·链表·stl·list
wespaul36 分钟前
一条自然语言命令的 49 个节点:可视化编排与每段强校验
前端·数据库
小白快快跑哦1 小时前
python-字符串全解(六):正则表达式-分组
python·mysql·正则表达式·分组
高级程序源9 小时前
django校园寻物通失物招领平台32261-计算机课程设计、毕业设计
vue.js·python·mysql·小程序·django·flask·课程设计