必须先执行SHOW VARIABLES LIKE 'slow_query_log'确认值为ON,再检查slow_query_log_file路径权限;long_query_time建议线上从1.0秒起步,支持微秒精度但旧版本向下取整;慢日志不记录纯写操作,需结合performance_schema定位真实瓶颈。

确认慢查询日志是否真在记录
很多 phpEnv 用户改完 my.ini 就以为日志开了,结果查了一周没一条记录——根本没生效。slow_query_log 默认是 OFF,long_query_time 默认是 10 秒,而 phpEnv 本地开发里跑个 1.2 秒的查询就卡顿,这个阈值毫无意义。
必须用命令确认当前值:
SHOW VARIABLES LIKE 'slow_query_log';<br>SHOW VARIABLES LIKE 'long_query_time';<br>SHOW VARIABLES LIKE 'slow_query_log_file';
重点检查三件事:
-
slow_query_log_file路径 MySQL 进程是否有写权限(phpEnv 的 MySQL 通常是 Windows 服务或非 root 用户启动,C:\phpEnv\MySQL\data\slow.log这类路径常因权限被静默丢弃) -
long_query_time建议设为0.5(支持小数),调试时甚至可临时设为0,但仅限本机 -
SET GLOBAL slow_query_log = ON只对新连接生效;已连上的 PHP 页面不会记录,要刷新页面或重启 Web 服务
用 mysqldumpslow 快速定位前 N 条慢 SQL
日志开启后,别直接打开 slow.log 逐行翻。Windows 下 phpEnv 自带 mysqldumpslow(位于 MySQL\bin\),直接命令行运行:
立即学习“PHP免费学习笔记(深入)”;
mysqldumpslow -s t -t 10 "C:\phpEnv\MySQL\data\slow.log"
这会按总耗时倒序输出最慢的 10 条语句。注意看每条记录里的 Rows_examined 和 Rows_sent:如果前者是后者的几百倍,基本就是索引没走或失效。
常见干扰项要过滤:
- 忽略
log_queries_not_using_indexes = ON产生的海量日志(比如查 3 行也记进来),phpEnv 本地调试初期建议保持OFF - 排除 phpEnv 自带的健康检查 SQL(如
SELECT 1、SHOW TABLES),专注你自己的业务表名和字段 - 若日志里全是
Prepare/Execute拆分形式(PDO 预处理常见),把Prepare后面的 SQL 拿出来单独分析,别只看Execute行
EXPLAIN 看执行计划,重点盯 type 和 Extra
拿到慢 SQL 后,不要急着改代码。在 phpMyAdmin 或命令行里加 EXPLAIN 前缀执行:
EXPLAIN SELECT * FROM orders WHERE user_id = 123 AND status = 'paid' ORDER BY created_at DESC;
关键看这几列:
-
type是ALL或index?说明全表/全索引扫描,必须建索引 -
key是NULL?不是没索引,而是没用上——常见于字段类型不一致(PHP 传字符串 ID,DB 字段是INT)、WHERE 里套了函数(WHERE DATE(created_at) = '2026-04-20')、或者联合索引顺序错位 -
Extra出现Using filesort或Using temporary?排序或分组没走索引,得把ORDER BY字段补进复合索引末尾
特别注意 phpEnv 的 MySQL 版本(通常 5.7 或 8.0):5.7 对 IN (subquery) 优化差,容易退化成 N+1;8.0 的 EXPLAIN FORMAT=TREE 更直观,但 phpMyAdmin 可能不支持,建议用命令行。
索引怎么建才不踩坑
phpEnv 是本地环境,数据量小,但索引逻辑和线上一致。别一上来就 ALTER TABLE xxx ADD INDEX (user_id),先看查询模式:
- 单条件高频查询(如后台列表按
status筛选)→ 单列索引够用,但避免在低基数字段(如is_deleted TINYINT)上建 - 多条件组合(如
WHERE category_id = ? AND is_hot = 1 ORDER BY sort_order)→ 建复合索引(category_id, is_hot, sort_order),严格按 WHERE + ORDER BY 顺序,且范围查询(>,BETWEEN)字段必须放最后 - 索引字段含字符串?用前缀索引节省空间:
ADD INDEX idx_title (title(32)),32 是经验值,太短可能失效,太长浪费内存 - 建完立刻
EXPLAIN验证,再用ANALYZE TABLE orders更新统计信息,否则优化器可能继续走旧计划
最容易被忽略的一点:phpEnv 的 MySQL 默认引擎是 InnoDB,但如果你手动建过 MyISAM 表,ORDER BY 在无索引时行为不同,且不支持事务——查慢了先 SHOW CREATE TABLE xxx 确认引擎。



















