先查slow_query_log=ON且log_output='FILE',再确认日志文件存在、有写权限并含最新时间戳;空则检查路径、权限或是否仅重载未重启。

怎么确认慢查询日志是否真在记录
宝塔面板点开「数据库 → MySQL 设置 → 性能调整」,看到「慢查询日志」显示“开启”不等于它真在写日志。常见假开启现象:日志路径权限不对、log_output被设成TABLE、或配置后只点了「重载配置」没重启 MySQL。
先验证状态:mysql -uroot -p -e "SHOW VARIABLES LIKE 'slow_query_log';" 返回 ON 且 log_output = 'FILE' 才算到位;再检查日志文件是否存在并有最近写入时间:ls -l /www/server/data/*slow* 或 tail -n 5 /www/server/data/mysql-slow.log。如果文件为空或报错“No such file”,说明路径错了或权限不足(MySQL 进程需对目录有写权限)。
用 mysqldumpslow 快速定位高频慢 SQL
别直接 cat 或 vim 打开几 MB 的慢日志——重复 SQL 被打散,人工看不出模式。用 MySQL 自带的 mysqldumpslow 做聚合:
-
mysqldumpslow -s at -t 10 /www/server/data/mysql-slow.log:按平均耗时排前 10 条 -
mysqldumpslow -s c -t 10 /www/server/data/mysql-slow.log:按执行次数排,抓高频语句
重点看三列:Count(执行频次)、Time=N.s (M.s)(单次均值和总耗时)、Rows=K.0 (L)(扫描行数)。比如 Rows=1245.0 (52290) 却只返回几十行,基本就是全表扫描了。
EXPLAIN 里必须盯住的三列:type、key、rows
EXPLAIN 不是看“有没有索引”,而是看“用得对不对”。在 MySQL 5.7 中,重点关注:
-
type出现ALL或INDEX:全表或全索引扫描,危险信号 -
key是NULL但possible_keys有值:优化器放弃可用索引,可能因统计信息过期,执行ANALYZE TABLE 表名;再试 -
rows显示扫描行数远超表总行数(如表 1 万行却扫 8 万行):索引选择错误,或 WHERE 条件导致索引失效(例如WHERE DATE(created_at) = '2024-01-01'对字段用了函数)
额外注意 Extra 列:Using filesort 或 Using temporary 意味着排序/分组没走索引,得靠联合索引覆盖 ORDER BY 或 GROUP BY 字段。
建联合索引时最容易踩的顺序坑
MySQL 的 B+ 树索引严格依赖定义顺序。例如查询是 WHERE status = 'pending' AND created_at > '2024-01-01' ORDER BY created_at DESC,建 INDEX idx_status_created (status, created_at) 才有效;反过来建 (created_at, status) 就无法加速 status 等值过滤。
几个硬约束:
- WHERE 中的等值条件放最左,范围/排序条件放右——
WHERE a = 1 AND b > 2 ORDER BY c→ 索引应为(a, b, c) - 低区分度字段(如
gender只有 'M'/'F')别放索引开头,可放到联合索引末尾 - 已有
(a)和(a,b),删掉单列(a),避免冗余
最后提醒一句:加完索引一定要回过头再跑一遍 EXPLAIN,确认 key 列真用了新索引,且 rows 显著下降——否则不是建错了,就是查询条件写法触发了隐式类型转换或函数包裹。











