Ubuntu PHP日志中的慢查询优化
Ubuntu PHP日志中的慢查询优化指南
一、慢查询日志配置(定位问题源头)
1. 启用MySQL慢查询日志
慢查询日志是识别数据库性能瓶颈的核心工具,需先配置MySQL记录执行时间超过阈值的查询。
编辑MySQL配置文件(路径通常为/etc/mysql/mysql.conf.d/mysqld.cnf
),添加或修改以下参数:
[mysqld]
slow_query_log = 1 # 开启慢查询日志
slow_query_log_file = /var/log/mysql/slow.log # 日志文件路径
long_query_time = 2 # 慢查询阈值(单位:秒,默认10秒,建议根据业务调整)
log_queries_not_using_indexes = 1 # 记录未使用索引的查询(可选,帮助优化索引)
保存后重启MySQL服务使配置生效:
sudo systemctl restart mysql
2. 配置PHP-FPM慢查询日志
PHP-FPM的慢日志可记录执行时间过长的PHP请求(包括数据库查询),帮助定位代码中的性能问题。
编辑PHP-FPM池配置文件(路径如/etc/php/7.4/fpm/pool.d/www.conf
,根据PHP版本调整),添加或修改以下参数:
[www]
request_slowlog_timeout = 1s # 慢请求阈值(单位:秒,建议从1秒开始逐步调整)
slowlog = /var/log/php-fpm/www-slow.log # 慢日志文件路径
重启PHP-FPM服务生效:
sudo systemctl restart php7.4-fpm
3. 查看慢日志
使用tail
命令实时查看慢日志,快速定位慢请求:
# 查看MySQL慢日志
tail -f /var/log/mysql/slow.log
# 查看PHP-FPM慢日志
tail -f /var/log/php-fpm/www-slow.log
二、数据库优化(解决核心瓶颈)
1. 分析慢查询日志
使用mysqldumpslow
(MySQL自带工具)或pt-query-digest
(Percona Toolkit工具)分析慢日志,找出高频慢查询。
示例(使用mysqldumpslow
):
# 按查询时间排序,显示前10条慢查询
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log
# 显示慢查询的详细信息(包括执行时间、执行次数、SQL语句)
mysqldumpslow -v -t 5 /var/log/mysql/slow.log
2. 添加合适的索引
索引是提升查询速度的关键,需为经常用于WHERE、JOIN、ORDER BY的字段添加索引。
- 使用
EXPLAIN
命令分析查询执行计划,确认是否使用了索引:
若EXPLAIN SELECT * FROM users WHERE email = 'test@example.com';
type
列为ALL
(全表扫描),则需添加索引:ALTER TABLE users ADD INDEX idx_email (email);
- 避免过度索引:索引会增加写操作(INSERT、UPDATE、DELETE)的开销,需权衡利弊。
3. 优化SQL查询
- **避免SELECT ***:只查询需要的字段,减少数据传输量。
-- 不推荐 SELECT * FROM orders WHERE user_id = 1; -- 推荐 SELECT id, order_number, amount FROM orders WHERE user_id = 1;
- 减少子查询和JOIN:尽量将子查询改为JOIN,或使用临时表存储中间结果。
- 使用批量操作:避免在循环中执行单条SQL,改用
INSERT INTO ... VALUES (...), (...), ...
或批量更新。
4. 定期维护数据库
- 优化表:定期执行
OPTIMIZE TABLE
命令,整理表碎片,提升查询效率(适用于InnoDB、MyISAM表)。OPTIMIZE TABLE users;
- 清理无用数据:定期删除过期数据(如日志表、临时表),减少表数据量。
三、PHP代码优化(减少不必要的开销)
1. 复用数据库连接
避免在每次请求中创建新的数据库连接,使用连接池(如PHP-FPM的pm
配置)或持久连接(PDO的PDO::ATTR_PERSISTENT
属性)。
示例(PDO持久连接):
$pdo = new PDO('mysql:host=localhost;
dbname=test', 'user', 'password', [
PDO::ATTR_PERSISTENT =>
true // 开启持久连接
]);
2. 使用预处理语句
预处理语句可防止SQL注入,并提高查询效率(避免SQL编译)。
示例(PDO预处理):
$stmt = $pdo->
prepare('SELECT * FROM users WHERE email = :email');
$stmt->
execute(['email' =>
$userEmail]);
$results = $stmt->
fetchAll();
3. 减少循环中的数据库查询
避免在循环中执行单条SQL,改用批量操作或JOIN查询。
示例(优化前:循环中查询):
foreach ($userIds as $userId) {
$stmt = $pdo->
prepare('SELECT name FROM users WHERE id = :id');
$stmt->
execute(['id' =>
$userId]);
$name = $stmt->
fetchColumn();
}
优化后(批量查询):
$placeholders = implode(',', array_fill(0, count($userIds), '?'));
$stmt = $pdo->
prepare("SELECT id, name FROM users WHERE id IN ($placeholders)");
$stmt->
execute($userIds);
$users = $stmt->
fetchAll(PDO::FETCH_KEY_PAIR);
// 返回[id =>
name]数组
4. 使用缓存技术
- OPcache:缓存PHP脚本的字节码,减少脚本加载和解析时间(需开启)。
编辑php.ini
文件:
重启PHP-FPM生效:[opcache] zend_extension=opcache.so opcache.enable=1 opcache.memory_consumption=128 # 缓存大小(MB,根据服务器内存调整) opcache.interned_strings_buffer=8 opcache.max_accelerated_files=4000 opcache.revalidate_freq=60 # 脚本更新检查频率(秒)
sudo systemctl restart php7.4-fpm
- Redis/Memcached:缓存频繁访问的数据库查询结果,减少数据库压力。
示例(使用Redis缓存):$redis = new Redis(); $redis-> connect('127.0.0.1', 6379); $cacheKey = "user_{ $userId} _data"; if ($redis-> exists($cacheKey)) { $userData = json_decode($redis-> get($cacheKey), true); } else { $stmt = $pdo-> prepare('SELECT * FROM users WHERE id = :id'); $stmt-> execute(['id' => $userId]); $userData = $stmt-> fetch(); $redis-> setex($cacheKey, 3600, json_encode($userData)); // 缓存1小时 }
5. 优化循环和递归
- 避免在循环中执行耗时操作(如文件IO、网络请求)。
- 减少递归深度,改用迭代方式实现递归逻辑。
四、PHP-FPM配置优化(提升并发处理能力)
1. 调整进程管理参数
编辑PHP-FPM池配置文件(如/etc/php/7.4/fpm/pool.d/www.conf
),优化以下参数:
[www]
pm = dynamic # 进程管理模式(动态调整进程数)
pm.max_children = 50 # 最大子进程数(根据服务器内存调整,每个进程约消耗10-20MB内存)
pm.start_servers = 5 # 启动时的子进程数
pm.min_spare_servers = 5 # 最小空闲子进程数(避免频繁创建进程)
pm.max_spare_servers = 35 # 最大空闲子进程数(避免占用过多内存)
pm.max_requests = 1000 # 每个子进程处理的最大请求数(避免内存泄漏)
重启PHP-FPM生效:
sudo systemctl restart php7.4-fpm
2. 调整请求超时时间
根据业务需求调整request_terminate_timeout
参数,避免长时间运行的脚本占用资源:
request_terminate_timeout = 30s # 超时时间(秒,建议设置为30-60秒)
五、系统级优化(提升整体性能)
1. 升级硬件
- 增加内存:PHP-FPM和MySQL都是内存密集型应用,足够的内存可减少磁盘IO。
- 使用SSD:SSD的读写速度远高于机械硬盘,可显著提升数据库和文件系统的性能。
2. 监控与告警
- 使用监控工具(如Prometheus+Granafa、Zabbix)监控服务器的CPU、内存、磁盘IO、MySQL性能指标(如QPS、TPS、慢查询数)。
- 设置告警规则,当慢查询数超过阈值或服务器资源使用率过高时,及时通知运维人员。
六、常用工具推荐
- 慢日志分析:
mysqldumpslow
、pt-query-digest
(Percona Toolkit)、Analyzed
(Composer包)。 - 性能分析:Xdebug(代码Profiler)、Blackfire(商业性能分析工具)、KCachegrind(可视化分析工具)。
- 数据库管理:phpMyAdmin(Web端管理)、MySQL Workbench(图形化管理)、Navicat(跨平台工具)。
- 缓存工具:Redis(内存数据库)、Memcached(分布式缓存)。
声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!
若转载请注明出处: Ubuntu PHP日志中的慢查询优化
本文地址: https://pptw.com/jishu/724052.html