本文目录导读:

- 第一步:确认日志是否开启及位置
- 第二步:看懂一条日志的核心字段(逐行拆解)
- 第三步:实战解读与排查策略(关键)
- 第四步:常见优化手段(对症下药)
- 第五步:实战案例(举一反三)
- 关键提示:PHP 自身的“慢日志”在哪?
在 PHP 项目中,慢查询日志通常指的是数据库(MySQL)层面的日志,而不是 PHP 自身的日志,解读它的核心目的是精准定位拖慢系统的 SQL 语句,并找到优化的切入点。
以下是系统的解读步骤和实战技巧:
第一步:确认日志是否开启及位置
你需要找到日志文件,在 MySQL 中,通常执行以下命令(如果在命令行):
SHOW VARIABLES LIKE 'slow_query_log%'; SHOW VARIABLES LIKE 'long_query_time';
- slow_query_log:是否开启(
ON或OFF)。 - slow_query_log_file:日志存放的物理路径。
- long_query_time:阈值(默认 10 秒,通常建议调低到 2 秒或 1 秒)。
第二步:看懂一条日志的核心字段(逐行拆解)
假设你从日志中抓取了这样一条记录:
# Time: 2023-10-01T10:23:45.123456Z # User@Host: root[root] @ localhost [127.0.0.1] Id: 12345 # Query_time: 5.234567 Lock_time: 0.002345 Rows_sent: 1000 Rows_examined: 500000 SET timestamp=1696148625; SELECT * FROM orders WHERE user_id = 101 AND status = 'completed' ORDER BY created_at DESC LIMIT 1000;
解读逻辑如下:
| 参数 | 含义 | 健康标准/警惕点 |
|---|---|---|
| Query_time | 总执行耗时(5.23秒) | 这是主角,若远高于阈值,说明 SQL 本身有问题或缺索引。 |
| Lock_time | 锁等待时间(0.002秒) | 通常较小,如果锁时间接近 Query_time,说明并发冲突严重(锁表/锁行)。 |
| Rows_examined | 扫描了多少行(50万行) | 重点排查项,如果这个数字巨大,且 Rows_sent 很小(1000),说明发生了全表扫描,这是主要优化方向。 |
| Rows_sent | 返回了多少行(1000行) | 通常业务需求决定的,如果发送太多,检查是否 SELECT * 或缺少 LIMIT。 |
| SET timestamp | 语句执行的具体时间戳 | 用于定位是业务高峰期还是定时任务导致的。 |
第三步:实战解读与排查策略(关键)
拿到一条日志后,按照以下顺序快速定位病根:
看 Rows_examined 与 Rows_sent 的比例
- 场景 A:
Examined比Sent大 100 倍以上。- 索引失效或缺失。
- 动作:直接对 WHERE 条件字段(
user_id,status)和排序字段(created_at)建立联合索引。
- 场景 B:
Examined与Sent差不多,但Query_time仍然很慢。- 数据量大,但可能是网络传输慢,或者是返回数据行数太多导致序列化时间长。
- 动作:检查是否需要分页(LIMIT),或减少
SELECT的字段(避免SELETE *)。
具体区分“慢”的类型
- 全是
Rows_examined大:优先加索引。 - 全是
Lock_time大:优先看数据库连接池,检查是否有长事务(事务未提交导致锁等待)。 - Query_time 大,但统计值都很小:可能是数据库服务器 CPU 繁忙,或查询涉及复杂的子查询/大表 JOIN。
看时间分布(Time 字段)
- 如果都在下午 2:00 - 3:00 集中出现,可能是定时任务(如数据同步)或报表跑批。
- 如果高并发时出现,通常是缓存失效导致并发穿透,或者慢 SQL 拖垮了数据库连接池。
第四步:常见优化手段(对症下药)
根据解读结果,通常采取以下措施:
- 加索引(最核心):对于
WHERE和ORDER BY的字段,建立复合索引,注意字段顺序(区分度高的放最左)。 - 改写 SQL:避免
SELECT *,避免LIKE '%xx'前置模糊查询,避免在索引列上做函数运算(如LEFT(phone, 3))。 - 分页优化:经典的深分页问题(
LIMIT 500000, 20),可改为WHERE id > 500000 LIMIT 20(延迟关联)。 - 未命中缓存:如果该 SQL 是高频查询且短小,可考虑在 Redis 中缓存结果集,减少数据库压力。
第五步:实战案例(举一反三)
案例日志:
# Query_time: 2.8 Lock_time: 0.0 Rows_sent: 10 Rows_examined: 400000
SELECT * FROM products WHERE category = 'electronics' AND price > 1000;
解读:扫描了 40 万行只给了 10 条,明显缺索引。
优化动作:
ALTER TABLE products ADD INDEX idx_cat_price (category, price);
执行后,Rows_examined 会骤降至 10 行左右,Query_time 下降至 0.01 秒。
关键提示:PHP 自身的“慢日志”在哪?
如果你看到的日志不是这种格式,而是类似于 [pool www] slow request(PHP-FPM 慢日志),那解读逻辑是另一回事,但目前 90% 的 PHP 性能瓶颈都在数据库慢查询,而非 PHP 本身。
补充建议:如果项目使用的是 Laravel 或 Symfony,请开启 DB::listen 事件监听,它可以直接在日志里打印 SQL 和参数,便于快速对应业务代码。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播