mysql 的 limit offset, count 越翻页越慢,因为需扫描 offset + count 行后丢弃前 offset 行;深分页应改用主键范围查询(如 where id > last_id order by id limit 10);不同数据库分页语法各异,且 limit 参数必须为常量整数。

MySQL 的 LIMIT offset, count 为什么越翻页越慢?
因为 MySQL 实际执行时,会先扫描 offset + count 行数据,再丢弃前 offset 行——哪怕你只要 1 条,它也可能扫了 800 万行。
- 第 1 页(
LIMIT 0, 10):扫 10 行,快 - 第 80 万页(
LIMIT 8000000, 10):扫 8000010 行,丢掉 800 万,只留 10 条 -
EXPLAIN看不出问题,但PROFILE里Sending data阶段耗时暴涨
怎么把深分页从秒级降到毫秒级?
用主键范围过滤替代 OFFSET,前提是表有单调递增的主键(如 id),且查询带 ORDER BY id。
- 先查出上一页最后一条的
id(比如是8000001) - 下一页直接写:
SELECT * FROM users WHERE id > 8000001 ORDER BY id LIMIT 10 - 不依赖
OFFSET,完全走主键索引,跳过所有已读数据 - 注意:如果业务要求按时间倒序,而
create_time有重复值,必须加id作为第二排序字段,否则分页结果可能错乱
不同数据库的分页语法差异在哪?
不是所有数据库都支持 LIMIT offset, count,跨库迁移或混合使用时容易出错。
本书以培养高级网站建设与管理人才为目标,内容循序渐进,由浅入深,通过大量的实例系统全面地介绍了Linux+PHP+MySQL环境下的网络后台开发技术。本书详尽分析了近30个典型案例。包括计数器、网站流量统计、留言板、论坛系统、聊天室、投票与调查、用户管理、新闻发布系统、广告轮播、购物系统等等,力求让读者通过对案例的学习,轻松掌握PHP和MySQL的编程精要,迅速掌握网络后台开发技巧。 本书适
- MySQL:支持
LIMIT 10 OFFSET 20和LIMIT 20, 10两种写法 - PostgreSQL:只认
LIMIT 10 OFFSET 20,不支持逗号语法 - SQL Server:必须用
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY,且ORDER BY不可省 - Oracle 12c+:支持类似 SQL Server 的
FETCH,老版本得套两层子查询用ROW_NUMBER()
LIMIT 参数不能写表达式,常见误写有哪些?
LIMIT 后的两个参数必须是常量整数,运行时不能计算,否则直接报错。
- ❌ 错误:
LIMIT (page-1)*10, 10(SQL 解析阶段就失败) - ❌ 错误:
LIMIT @offset, @limit(除非在存储过程中预设变量,否则客户端传参需自行拼接) - ❌ 错误:
LIMIT 10, -1(MySQL 早就不支持负数,报ERROR 1064) - ✅ 正确:应用层算好值再传,比如 page=3、size=10 → 拼成
LIMIT 20, 10
分页不是“写对就行”,而是“写对 + 排序稳 + 主键可推 + 参数可控”。尤其当页码超过 1000 页,OFFSET 就不再是语法问题,而是性能事故的起点。









