explain 是定位慢 sql 最有效方式,可直观显示是否走索引、扫描行数、是否用临时表或排序;需警惕 type 为 all/index、key 为 null、rows 远超结果数、extra 出现 filesort/temporary;避免 where 函数操作、隐式类型转换等索引失效写法。

直接用 EXPLAIN 看执行计划,是定位慢 SQL 最有效、最不绕弯的方式。它不依赖日志、不猜测逻辑,只告诉你 MySQL 实际怎么查的——有没有走索引、扫描多少行、是否临时表、是否排序,一目了然。
一、在接口中快速捕获可疑 SQL
别等用户投诉再查。在 PHP 接口关键查询前加一行日志,把完整 SQL 打出来(注意脱敏);或者用 Xdebug + MySQL 的 general_log 临时开启记录。更轻量的做法是:在开发/测试环境的数据库连接后执行 SET profiling = 1,然后用 SHOW PROFILES 找耗时最高的 query ID,再用 SHOW PROFILE FOR QUERY N 看详细阶段耗时。
二、读懂 EXPLAIN 输出的关键列
type:连接类型,ALL(全表扫描)和 index(全索引扫描)要警惕;优先看到 ref、range、const。
key:实际使用的索引名。为 NULL 就代表没走索引。
rows:MySQL 预估扫描行数。如果比表总行数还大,或远超返回结果数(比如查 1 条却扫 50 万行),说明索引失效或条件写法有问题。
Extra:重点看 Using filesort(触发额外排序)、Using temporary(建临时表)、Using join buffer(块嵌套循环性能差)——这些往往是性能拐点。
三、常见“看似有索引,实则失效”的写法
- WHERE 子句对字段做函数操作:
WHERE DATE(create_time) = '2024-01-01'→ 改成WHERE create_time >= '2024-01-01' AND create_time - 隐式类型转换:
WHERE user_id = '123'(user_id 是 INT)→ 字符串强制转数字,可能丢索引 - LIKE 左模糊:
WHERE name LIKE '%关键词'→ 无法用 B+ 树索引,考虑全文索引或倒排表 - 联合索引顺序错位:
INDEX (a,b,c),但只查WHERE b = ?→ a 没出现在条件里,索引失效
四、PHP 中安全又高效的优化实践
- 用 PDO::prepare + execute 绑定参数,避免拼接 SQL,也利于 MySQL 缓存执行计划
- 分页别用
LIMIT 100000, 20,改用游标分页:WHERE id > ? ORDER BY id LIMIT 20 - 大表 COUNT(*) 很慢?用缓存计数(如 Redis)或近似值(
SHOW TABLE STATUS中的 Rows) - 单条 SQL 太重?拆成多个小查询,用 PHP 合并(尤其跨维度关联时,比 JOIN 更可控)
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











