讲师中心 微信公众号
AI工具推荐 视频效率加速

ThinkPHP 5.1 优化 MySQL 深分页(Deep Paging)查询【Limit】

落芳酱_1047

落芳酱_1047

发布时间:2026-07-09 15:03:26

|

830人浏览过

|

来源于php中文网

原创

ThinkPHP 5.1 十万级数据分页变慢的根本原因是 MySQL 的 LIMIT offset, size 导致全表扫描前 offset 行;解决方案包括关闭 totalCount、使用 simple 分页、添加复合索引 (user_id, create_time)、确保字段 NOT NULL,并改用基于 id 的游标分页替代 offset 分页。

thinkphp 5.1 优化 mysql 深分页(deep paging)查询【limit】

ThinkPHP 5.1 应用在数据量超过十万级后,用户翻到第200页、第500页时页面加载明显变慢,甚至超时,根本原因是 MySQL 执行 LIMIT 9990, 20 类查询时被迫扫描并丢弃前9990行——这不是 PHP 层能绕开的数据库底层瓶颈。

关闭 totalCount 统计跳过 COUNT(*) 全表扫描

默认 paginate() 会执行两条 SQL:一条 SELECT COUNT(*) 算总数,一条 SELECT LIMIT 取数据。COUNT(*) 在无索引或大表上可能耗时数百毫秒甚至秒级。

第一步:在控制器中调用 paginate 时,将第二个参数设为 false:

$list = Db::name('order')->where('user_id', $uid)->paginate(20, false);

立即学习“PHP免费学习笔记(深入)”;

第二步:视图中渲染分页 HTML 时,改用 simple 模式避免依赖总页数:

{$list->simple()->render()}

第三步:若需保留搜索参数(如 ?keyword=abc&page=3),必须显式追加:

{$list->simple()->appends(request()->param())->render()}

这一步不补 appends,翻页后所有 GET 参数都会丢失,搜索结果无法持续。

用联合索引让 WHERE + ORDER 快速定位起始行

即使关掉 COUNT,如果 LIMIT 起始位置无法通过索引直接跳转,MySQL 仍要从头扫描。关键不是“有没有索引”,而是“索引是否覆盖 WHERE 条件 + ORDER BY 字段”。

方法一:检查当前查询是否走索引

执行 EXPLAIN SELECT * FROM order WHERE user_id = 123 ORDER BY create_time DESC LIMIT 20;,确认 【type 不是 ALL,key 显示实际索引名】。

方法二:建复合索引,顺序必须严格匹配查询逻辑

WHERE 先过滤 user_id,再按 create_time 倒序排列,索引字段顺序就得是 (user_id, create_time):

ALTER TABLE `order` ADD INDEX idx_uid_ctime (user_id, create_time DESC);

注意:MySQL 8.0+ 支持降序索引,5.7 及以下版本会忽略 DESC,但依然能用该索引加速 ORDER BY。

MySQL
MySQL

编写正确的MySQL查询,避免字符集、索引和锁方面的常见陷阱。

下载

方法三:强制 NOT NULL 并验证字段可索引性

如果 create_time 允许 NULL,MySQL 可能放弃使用该索引。执行 ALTER TABLE `order` MODIFY COLUMN create_time DATETIME NOT NULL; 再重建索引。

替换 offset 分页为游标分页(Cursor-based)

当用户滑动到第 1000 页以上,offset 分页已不可逆地成为性能毒药。游标分页不依赖页码,只依赖上一页最后一条记录的锚点值,彻底避开 OFFSET 扫描。

方法1:基于自增主键 id 的区间查询(最稳定)

首次请求:取最新20条 → SELECT * FROM order WHERE user_id = 123 ORDER BY id DESC LIMIT 20;

下一页请求:带上上一页最小 id(假设为 8842)→ SELECT * FROM order WHERE user_id = 123 AND id

方法2:基于时间戳 + 主键防重复(适用于 create_time 可能重复场景)

首次请求:取最新20条 → SELECT id, user_id, create_time, title FROM order WHERE user_id = 123 ORDER BY create_time DESC, id DESC LIMIT 20;

下一页请求:带上上一页最后一条的 (create_time, id) 作为边界 → SELECT ... WHERE user_id = 123 AND (create_time, id)

这一步必须用 【ORDER BY create_time DESC, id DESC】双字段排序】,否则时间相同的数据会乱序,导致漏查或重复。

方法3:在 ThinkPHP 5.1 中封装游标逻辑(不依赖 paginate)

控制器中手动构造查询:

$last_id = input('last_id/d', 0);

$map = ['user_id' => $uid];

if ($last_id > 0) { $map['id'] = ['

$list = Db::name('order')->where($map)->order('id DESC')->limit(20)->select();

前端分页链接传参只需 ?last_id=8842,无需 page 参数,URL 更干净,也杜绝了恶意传入极大 page 值触发深 offset 查询。

灵契少女相关攻略
《灵契少女》阴间宝箱获取攻略 《灵契少女》第一章生命之树探索攻略 《灵契少女》拉卡镇全宝箱收集攻略
《灵契少女》静寂林地全宝箱收集攻略 揭秘《灵契少女》中的冰魄秘剑 《灵契少女》幽光果分布位置一览
《灵契少女》肿胀之心技能效果分享 sql中%的含义 快速掌握sql中%的作用 mysql中%的用法 mysql通配符%使用场景
如何在PostgreSQL中使用OFFSET实现SQL分页查询功能? 如何在MySQL中利用UNION运算符合并两个SQL查询结果? 为什么MySQL在执行UNION操作时性能远低于UNION ALL?
如何在SQL中实现类似于Excel的分类汇总功能? 如何解决MySQL中GROUP BY查询结果与预期不符的问题? 如何在SQL中实现对非数值类型字段的自定义规则聚合?
MySQL中UNION与UNION ALL区别 如何在SQL中利用GROUP BY和HAVING子句过滤聚合后的数据? 如何利用SQL聚合函数快速查找表中的重复记录?
如何使用SQL聚合结果作为子查询的过滤条件? SQL如何实现对分组后的数据进行二次筛选与排序? 如何使用SQL聚合函数统计异常日志的出现频率?
为什么MySQL在执行Union操作时如果不加All会产生额外的索引压力? SQL中如何使用HAVING过滤GROUP BY的分组结果? 如何在SQL中使用分组函数进行数据清洗?
如何在SQL嵌套查询中使用集合运算符(Union/Intersect)进行过滤? 如何在PostgreSQL中使用复杂聚合函数进行分组? 为什么在SQL查询中聚合函数不能直接出现在WHERE子句里?
SQL分组查询中HAVING与WHERE有什么本质区别? 如何通过限制查询返回行数减轻SQL注入危害? 为什么Navicat 15在生成ER图时无法显示字段的完整描述信息?

相关文章

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
二狗PPT
二狗PPT Hot

一款AI演示文稿工具,主要用于专为中式职场打造的AI PPT生成工具,适合需要提升相关任务效率的用户。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

相关专题

更多
mysql修改数据表名
mysql修改数据表名

MySQL修改数据表:1、首先查看数据库中所有的表,代码为:‘SHOW TABLES;’;2、修改表名,代码为:‘ALTER TABLE 旧表名 RENAME [TO] 新表名;’。php中文网还提供MySQL的相关下载、相关课程等内容,供大家免费下载使用。

1973

2023.06.20

MySQL创建存储过程
MySQL创建存储过程

存储程序可以分为存储过程和函数,MySQL中创建存储过程和函数使用的语句分别为CREATE PROCEDURE和CREATE FUNCTION。使用CALL语句调用存储过程智能用输出变量返回值。函数可以从语句外调用(通过引用函数名),也能返回标量值。存储过程也可以调用其他存储过程。php中文网还提供MySQL创建存储过程的相关下载、相关课程等内容,供大家免费下载使用。

1219

2023.06.21

mongodb和mysql的区别
mongodb和mysql的区别

mongodb和mysql的区别:1、数据模型;2、查询语言;3、扩展性和性能;4、可靠性。本专题为大家提供mongodb和mysql的区别的相关的文章、下载、课程内容,供大家免费下载体验。

715

2023.07.18

mysql密码忘了怎么查看
mysql密码忘了怎么查看

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS 应用软件之一。那么mysql密码忘了怎么办呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2572

2023.07.19

mysql创建数据库
mysql创建数据库

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS 应用软件之一。那么mysql怎么创建数据库呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

4248

2023.07.25

mysql默认事务隔离级别
mysql默认事务隔离级别

MySQL是一种广泛使用的关系型数据库管理系统,它支持事务处理。事务是一组数据库操作,它们作为一个逻辑单元被一起执行。为了保证事务的一致性和隔离性,MySQL提供了不同的事务隔离级别。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

999

2023.08.08

sqlserver和mysql区别
sqlserver和mysql区别

SQL Server和MySQL是两种广泛使用的关系型数据库管理系统。它们具有相似的功能和用途,但在某些方面存在一些显著的区别。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

4511

2023.08.11

mysql忘记密码
mysql忘记密码

MySQL是一种关系型数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。那么忘记mysql密码我们该怎么解决呢?php中文网给大家带来了相关的教程以及其他关于mysql的文章,欢迎大家前来学习阅读。

4082

2023.08.14

Buffalo框架数据库开发全教程
Buffalo框架数据库开发全教程

本专题围绕Buffalo框架数据库开发,讲解database.yml多环境配置、soda与fizz迁移生成回滚、模型结构体标签、增删改查与条件查询、一对多与多对多关联、数据校验、回调钩子、事务处理及原生SQL执行能力。

60

2026.09.23

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn