MySQL性能优化
慢查询日志
-- 开启慢查询日志
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 1; -- 记录超过 1 秒的查询
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
SET GLOBAL log_queries_not_using_indexes = ON;
-- 用 pt-query-digest 分析
pt-query-digest /var/log/mysql/slow.log
-- 查找最慢的查询
SELECT query_time, lock_time, rows_sent, rows_examined, sql_text
FROM mysql.slow_log
ORDER BY query_time DESC
LIMIT 10;
EXPLAIN 输出解读
EXPLAIN SELECT * FROM orders o
JOIN users u ON o.user_id = u.id
WHERE o.status = 'pending' AND o.created_at > '2024-01-01';
-- 关键列:
-- type: ALL(全表扫描)| ref | range | const(最好)
-- key: 使用的索引(NULL = 未使用索引)
-- rows: 预估扫描行数(越小越好)
-- Extra: Using filesort / Using temporary(警告信号)
-- 获取实际执行统计(MySQL 8.0+)
EXPLAIN ANALYZE SELECT ...;
索引最佳实践
-- 组合索引——列顺序很重要!
-- 适用于:WHERE status = 'active' AND user_id = 42
-- 适用于:WHERE status = 'active'
-- 不适用:WHERE user_id = 42(必须从左开始)
CREATE INDEX idx_status_user ON orders(status, user_id);
-- 覆盖索引(包含所有查询列)
CREATE INDEX idx_order_cover ON orders(user_id, status, created_at, total);
-- 查找未使用的索引
SELECT * FROM sys.schema_unused_indexes;
关键配置参数
| 参数 | 建议值 | 影响 |
|---|---|---|
| innodb_buffer_pool_size | RAM 的 70-80%(16G 服务器设 8G) | 最关键——缓存数据和索引 |
| innodb_log_file_size | 1-4 GB | 事务写入性能 |
| innodb_flush_log_at_trx_commit | 2(性能优先)或 1(ACID 优先) | 写入持久性与性能权衡 |
| max_connections | 150-500(使用连接池) | 防止资源耗尽 |
| query_cache_type | 0(禁用——8.0 已废弃) | 避免缓存互斥竞争 |