LIMIT 越往后越慢是因为MySQL需扫描并暂存前offset+rows行再丢弃前offset行,导致I/O和CPU开销线性增长;覆盖索引须包含SELECT和ORDER BY所有字段且符合最左前缀原则;用WHERE id
为什么
LIMIT越往后越慢?MySQL 执行
LIMIT 10000, 20时,不是跳过前 1 万行直接取 20 行,而是先扫描并暂存前 10020 行,再丢弃前 10000 行——这导致 I/O 和 CPU 开销随偏移量线性增长。尤其当ORDER BY字段没索引、或索引无法覆盖查询字段时,全表扫描或临时文件排序会进一步放大延迟。覆盖索引怎么写才真正生效?
覆盖索引要求:查询的所有字段(包括
ORDER BY和SELECT列)都必须包含在同一个联合索引中,且顺序要匹配最左前缀原则和排序需求。
- 错误写法:
INDEX (create_time)—— 只能加速排序,但查id和title还得回表- 正确写法:
INDEX (create_time, id, title)—— 假设你按create_time DESC排序,并SELECT id, title- 注意:如果
WHERE条件存在(如status = 1),应把过滤字段放索引最左侧:INDEX (status, create_time, id, title)用主键 ID 替代 OFFSET 的实际写法
适用于按主键或时间递增排序的场景,本质是把“跳过 N 行”转为“从某 ID 开始取”。避免
LIMIT的偏移成本,但要求前端能记住上一页最后一条的id值。
win可用的mysql指令skill下载安装、修复、更新或打包一个基于 Python 和 PyMySQL 实现的 Windows `mysql` 命令。适用于用户希望在 PowerShell/CMD 中输入 `mysql` 时重定向到 Python 实现、需要交互式输入 MySQL 连接信息、需要同步到当前用户本地 bin 目录,或需要将该能力封装成可公开复用的 Codex skill。
- 原低效语句:
SELECT id, title FROM article ORDER BY id DESC LIMIT 10000, 20- 优化后:
SELECT id, title FROM article WHERE id (假设上一页最大id是 123456)- 关键点:必须确保
id严格递增、无重复、不删除后复用;否则需用复合条件(如WHERE (create_time, id) )哪些情况覆盖索引也救不了?
覆盖索引不是银弹。以下场景即使加了索引,性能仍可能卡在别处:
GROUP BY或DISTINCT导致临时表 + 文件排序,索引失效- 查询字段含
TEXT/BLOB类型,MySQL 无法将其加入索引,强制回表- 使用函数包裹排序字段,如
ORDER BY DATE(create_time),索引无法用于排序- MySQL 版本低于 5.7 时,
JSON字段或虚拟列上的索引支持有限,覆盖效果打折扣分页性能问题从来不是单点问题——索引设计、查询结构、数据分布、甚至客户端如何传参,都在同一条链路上。最容易被忽略的是:你以为加了索引就覆盖了全部字段,结果
EXPLAIN里还躺着一个Using filesort或Using temporary。












