慢查询日志是分析MySQL查询速度慢的核心工具,可记录执行时间超过阈值的SQL语句,帮助快速定位问题。
SHOW VARIABLES LIKE 'slow_query_log'(查看是否开启)、SHOW VARIABLES LIKE 'long_query_time'(查看慢查询阈值,默认10秒)、SHOW VARIABLES LIKE 'slow_query_log_file'(查看日志文件路径)。SET GLOBAL slow_query_log = 'ON'、SET GLOBAL long_query_time = 1(将阈值设为1秒,可根据需求调整)。/etc/my.cnf(或/etc/mysql/my.cnf),在[mysqld]部分添加:slow_query_log = ON
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
log_queries_not_using_indexes = 1 # 记录未使用索引的查询(可选)
systemctl restart mysqld(CentOS 7+)或service mysql restart(CentOS 6)。mysqldumpslow(MySQL自带)或pt-query-digest(Percona Toolkit)解析日志:
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log:按执行时间排序,显示最慢的10条查询。pt-query-digest /var/log/mysql/slow.log:生成详细报告,重点关注高频、耗时长的SQL。EXPLAIN可展示SQL的执行路径,帮助识别索引使用、表连接等问题。
EXPLAIN,例如EXPLAIN SELECT * FROM orders WHERE user_id = 123 AND status = 'paid'。range(范围扫描)、ref(索引查找)、eq_ref(主键/唯一索引关联),避免ALL(全表扫描)。Using filesort(文件排序)、Using temporary(临时表),说明查询存在性能隐患,需优化。索引是提升查询速度的关键,但不合理的索引会增加插入、更新开销。
WHERE、JOIN、ORDER BY的列创建索引,例如ALTER TABLE orders ADD INDEX idx_user_status (user_id, status)(联合索引)。SELECT user_id, status FROM orders WHERE user_id = 123,若(user_id, status)有索引,则无需访问表数据)。OPTIMIZE TABLE或ALTER TABLE ... REBUILD INDEX整理索引碎片,保持索引高效性。合理的配置参数能充分利用服务器资源,提升查询性能。
innodb_buffer_pool_size是InnoDB存储引擎最重要的参数,用于缓存数据和索引,建议设置为物理内存的50%-80%(例如服务器有16GB内存,可设为12GB):innodb_buffer_pool_size = 12G
innodb_log_file_size控制重做日志文件大小,较大的日志文件可减少日志切换频率,提升写入性能,建议设置为256M-512M:innodb_log_file_size = 512M
max_connections设置最大并发连接数,根据服务器性能和应用需求调整(例如设为500),避免过多连接导致资源耗尽:max_connections = 500
tmp_table_size和max_heap_table_size控制临时表的最大大小,避免大查询使用磁盘临时表(影响性能),建议设置为256M-512M:tmp_table_size = 512M
max_heap_table_size = 512M
sort_buffer_size(排序缓冲区)、join_buffer_size(连接缓冲区)根据查询需求调整,例如sort_buffer_size = 2M、join_buffer_size = 2M。SQL语句的编写方式直接影响查询性能,需遵循以下原则:
SELECT user_id, status FROM orders代替SELECT * FROM orders)。ON orders.user_id = users.id,user_id和id都应有索引)。LIMIT 10000, 10(需扫描10010行),可采用覆盖索引或子查询优化(例如SELECT * FROM orders WHERE id > (SELECT id FROM orders ORDER BY id LIMIT 10000, 1) LIMIT 10)。SELECT * FROM orders WHERE user_id IN (SELECT id FROM users WHERE status = 'active')改为SELECT orders.* FROM orders JOIN users ON orders.user_id = users.id WHERE users.status = 'active')。定期维护可保持数据库性能稳定,避免碎片化等问题。
OPTIMIZE TABLE命令整理表碎片,释放空间(适用于MyISAM和InnoDB表):OPTIMIZE TABLE orders;
ANALYZE TABLE命令更新表的统计信息,帮助优化器生成更优的执行计划:ANALYZE TABLE orders;
```。
缓存可显著减少对数据库的直接访问,提升查询速度。
硬件性能是数据库运行的基础,需根据负载调整:
innodb_buffer_pool_size设置为更大的值)。noatime选项(减少文件访问时间的记录开销),例如:mount -o remount,noatime /var/lib/mysql
```。