ThinkPHP 无法自动分析索引命中情况,必须将框架生成的 SQL 拿到数据库中执行 EXPLAIN 才能准确判断;需关注 type、key、rows 字段,并避免 like '%xxx'、函数操作等导致索引失效的写法。
ThinkPHP 本身不提供数据库索引命中分析能力,所有索引是否被命中、是否走全表扫描,必须依赖底层数据库(如 MySQL)的
输出来判断——框架层只负责生成 SQL,不参与执行计划解析。
怎么看 ThinkPHP 生成的 SQL 是否走了索引
核心是把 ThinkPHP 构建出的 SQL 拿到数据库里手动执行
,不能只看框架日志里的 SQL 字符串就下结论。
开启 ThinkPHP 的 SQL 日志:在配置中设
或使用
获取上一条 SQL
复制该 SQL,粘贴进 MySQL 客户端(如 MySQL Shell、Navicat 或
),前面加
(注意有空格)再执行
重点看
结果中的
(
/
/
是好信号,
表示全表扫描)、
(实际使用的索引名)、
(预估扫描行数)
注意 ThinkPHP 的
条件若含 PHP 变量拼接(如字符串插值)、或用了
、或对字段做了函数操作(如
),MySQL 很可能直接放弃索引
ThinkPHP 查询写法如何影响索引选择
框架的链式调用看似“高级”,但最终翻译成 SQL 后,是否能命中索引,完全取决于生成的 WHERE 条件结构和字段索引定义是否匹配。
→ 生成
,若
有单列索引或联合索引最左前缀,通常可命中
→ 生成
,无法使用 B+Tree 索引,必全表扫描
→ 若存在联合索引
,可命中;但若索引是
,则只有
单独条件时无法利用
→ 对字段应用函数,索引失效;应改写为
TP6/TP8 中开启慢查询 + 自动 EXPLAIN 的实用技巧
开发期快速定位低效查询,可临时在数据库中间件或 BaseQuery 类中注入
分析逻辑,但要注意仅限调试环境启用。
PHP 8.5.5
PHP 8.5.5 是 PHP 8.5 分支的维护更新版本。该版本延续了“小步快跑”的迭代逻辑,通过深度错误修复、底层性能微调以及安全加固,旨在为开发者提供一个更健壮、更高效的运行环境。该版本严格遵守语义化版本规范,不包含破坏性变更。
下载
立即学习
“
PHP免费学习笔记(深入)
”;
在
中注册一个数据库查询后置中间件,捕获
,对
语句自动补
并记录到日志(需判断非调试环境跳过)
避免在生产环境开启,因为每次查询多一次
执行,本身就有开销
更稳妥的做法是结合 MySQL 的慢查询日志(
,
),再用
或
分析,比框架层拦截更可靠
TP8 的
场景下,注意连接复用可能导致
结果缓存错乱,务必在独立连接中执行
真正卡顿的往往不是 ThinkPHP 的语法糖,而是 WHERE 条件和索引设计之间的错配。与其反复调优
或
,不如花 10 分钟用
看清一行 SQL 到底扫了多少行数据——很多“优化”根本不需要改代码,只改一个索引就解决了。
EXPLAINEXPLAIN'show_sql' => trueDb::getLastSql()mysql -u root -pEXPLAIN EXPLAINtypeconstrefrangeALLkeyrowswherelike '%xxx'where('DATE(create_time)', '2024-01-01')where('status', 1)WHERE status = 1statuswhere('name', 'like', '%abc')WHERE name LIKE '%abc'where(['status' => 1, 'category_id' => 5])(status, category_id)(category_id, status)statuswhereRaw('UNIX_TIMESTAMP(create_time) > 1700000000')where('create_time', '>', '2023-11-15 00:00:00')EXPLAINapp/middleware.php$query->getLastSql()SELECTEXPLAINEXPLAINslow_query_log=ONlong_query_time=0.5mysqldumpslowpt-query-digestthink-swooleEXPLAINwithfieldEXPLAIN