ThinkPHP大表分页性能优化,有哪些替代游标分页的方法?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1067个文字,预计阅读时间需要5分钟。
由于使用`paginate() 默认基于 OFFSET + LIMIT,数据量一旦超过百万,使用 OFFSET 50000 这类查询就会全表扫描到第五百万行,MySQL 执行计划里经常出现 `Using filesort` 或 `Using temporary`,导致 CPU 和 I/O 等资源压力巨大。
真实场景下,用户翻到第 200 页(每页 25 条)时,OFFSET 4999 已经明显卡顿;到第 1000 页,响应可能超 3 秒甚至超时。
- 不是 TP 框架问题,是 SQL 分页模型本身在大数据量下的通病
-
paginate()不支持自动改写为游标分页,得手动绕开 - 如果表没合适单调递增字段(比如
id或create_time),游标分页也难落地
ThinkPHP 实现游标分页的最小可行写法
核心思路:不用 OFFSET,改用 WHERE id > ? ORDER BY id LIMIT N,靠上一页最后一条记录的 id 做“锚点”。
本文共计1067个文字,预计阅读时间需要5分钟。
由于使用`paginate() 默认基于 OFFSET + LIMIT,数据量一旦超过百万,使用 OFFSET 50000 这类查询就会全表扫描到第五百万行,MySQL 执行计划里经常出现 `Using filesort` 或 `Using temporary`,导致 CPU 和 I/O 等资源压力巨大。
真实场景下,用户翻到第 200 页(每页 25 条)时,OFFSET 4999 已经明显卡顿;到第 1000 页,响应可能超 3 秒甚至超时。
- 不是 TP 框架问题,是 SQL 分页模型本身在大数据量下的通病
-
paginate()不支持自动改写为游标分页,得手动绕开 - 如果表没合适单调递增字段(比如
id或create_time),游标分页也难落地
ThinkPHP 实现游标分页的最小可行写法
核心思路:不用 OFFSET,改用 WHERE id > ? ORDER BY id LIMIT N,靠上一页最后一条记录的 id 做“锚点”。

