一、为什么需要SQL优化? SQL优化是数据库性能提升的核心,合理优化可以让查询速度提升几十甚至几百倍。
1.1 慢查询的影响 1 2 3 4 5 6 7 8 9 10 ┌─────────────────────────────────────────────────────────────────┐ │ 慢查询的影响 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 🚫 用户体验差 → 页面加载慢,流失用户 │ │ 💰 资源消耗大 → CPU 、内存、IO飙升 │ │ 🔒 连接耗尽 → 其他请求无法获取连接 │ │ 💣 引发故障 → 严重时导致数据库宕机 │ │ │ └─────────────────────────────────────────────────────────────────┘
1.2 优化目标
指标
说明
优化建议
响应时间
SQL执行时间
< 100ms
吞吐量
每秒查询数
根据业务需求
资源占用
CPU/内存/IO
合理利用
二、慢查询日志 2.1 开启慢查询日志 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 SHOW VARIABLES LIKE 'slow_query_log' ;SET GLOBAL slow_query_log = 'ON' ;SET GLOBAL long_query_time = 2 ;SHOW VARIABLES LIKE 'long_query_time' ;SET GLOBAL log_queries_not_using_indexes = 'ON' ;SHOW VARIABLES LIKE 'slow_query_log_file' ;
2.2 配置文件永久生效 1 2 3 4 5 [mysqld] slow_query_log = 1 slow_query_log_file = /var/log/mysql/slow.loglong_query_time = 2 log_queries_not_using_indexes = 1
2.3 分析慢查询日志 1 2 3 4 5 6 7 8 9 10 mysqldumpslow -s t -t 10 /var/log/mysql/slow.log mysqldumpslow -s c -t 20 /var/log/mysql/slow.log mysqldumpslow -s t -t 10 /var/log/mysql/slow.log
三、EXPLAIN分析 3.1 EXPLAIN基本使用 1 2 3 4 5 6 7 EXPLAIN SELECT * FROM users WHERE id = 1 ; EXPLAIN SELECT u.name, o.total FROM users u INNER JOIN orders o ON u.id = o.user_id WHERE u.age > 25 ;
3.2 EXPLAIN结果字段
字段
说明
id
查询序号,越大越先执行
select_type
查询类型
table
访问的表
type
连接类型(重要)
possible_keys
可能使用的索引
key
实际使用的索引
key_len
索引长度
ref
与索引比较的列
rows
扫描行数(重要)
Extra
额外信息(重要)
3.3 type(连接类型)
类型
说明
性能
const
主键或唯一索引查找
最好
eq_ref
唯一索引连接
好
ref
非唯一索引查找
一般
range
索引范围查询
一般
index
全索引扫描
较差
ALL
全表扫描
最差
1 2 3 4 5 6 7 ┌─────────────────────────────────────────────────────────────────┐ │ type 性能排序 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 最好 ← const → eq_ref → ref → range → index → ALL → 最差 │ │ │ └─────────────────────────────────────────────────────────────────┘
值
说明
Using filesort
需要额外排序,效率低
Using temporary
使用临时表,效率低
Using index
使用索引覆盖,不需要回表
Using where
使用WHERE过滤
Using index condition
索引下推
四、SQL优化技巧 4.1 避免全表扫描 1 2 3 4 5 6 7 8 9 10 SELECT * FROM users WHERE age + 1 = 26 ;SELECT * FROM users WHERE LEFT (name, 1 ) = '张' ;SELECT * FROM users WHERE age = 25 ;SELECT * FROM users WHERE name LIKE '张%' ;SELECT id, name, age FROM users WHERE age = 25 ;
4.2 避免索引失效 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 SELECT * FROM users WHERE YEAR (created_at) = 2026 ;SELECT * FROM users WHERE created_at >= '2026-01-01' AND created_at < '2027-01-01' ;SELECT * FROM users WHERE id = '1' ; SELECT * FROM users WHERE id = 1 ;SELECT * FROM users WHERE name IS NULL ;SELECT * FROM users WHERE name = '' OR name IS NULL ;
4.3 优化LIMIT分页 1 2 3 4 5 6 7 8 9 10 SELECT * FROM users ORDER BY id LIMIT 100000 , 10 ;SELECT * FROM users WHERE id > 100000 ORDER BY id LIMIT 10 ;SELECT * FROM users WHERE id >= (SELECT id FROM users ORDER BY id LIMIT 100000 , 1 ) LIMIT 10 ;
4.4 优化JOIN 1 2 3 4 5 6 7 8 9 10 11 12 13 SELECT * FROM users u INNER JOIN orders o ON u.id = o.user_id;ALTER TABLE orders ADD INDEX idx_user_id (user_id);SELECT * FROM users WHERE id IN (SELECT user_id FROM orders);SELECT u.* FROM users u INNER JOIN orders o ON u.id = o.user_id;
4.5 优化聚合函数 1 2 3 4 5 6 7 8 9 SELECT COUNT (* ) FROM users WHERE age > 25 ;SELECT COUNT (* ) FROM users USE INDEX (idx_age);ALTER TABLE orders ADD COLUMN monthly_count INT DEFAULT 0 ;
五、实战案例 5.1 案例一:分页查询优化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 SELECT * FROM orders ORDER BY created_at DESC LIMIT 10000 , 10 ;SELECT * FROM orders WHERE id > (SELECT id FROM orders ORDER BY id LIMIT 10000 , 1 )ORDER BY id LIMIT 10 ;SELECT * FROM orders WHERE created_at < '2026-01-01' ORDER BY created_at DESC LIMIT 10 ;SELECT o.* FROM orders o INNER JOIN (SELECT id FROM orders ORDER BY id LIMIT 10000 , 10 ) t ON o.id = t.id;
5.2 案例二:COUNT(*)优化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 SELECT COUNT (* ) FROM orders WHERE status = 1 ;ALTER TABLE orders ADD INDEX idx_status (status);SELECT COUNT (* ) FROM orders WHERE status = 1 ;SHOW TABLE STATUS LIKE 'orders' ;CREATE TABLE order_stats ( date DATE PRIMARY KEY , total_count INT DEFAULT 0 , paid_count INT DEFAULT 0 );
5.3 案例三:复杂查询优化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 SELECT u.name, (SELECT COUNT (* ) FROM orders WHERE user_id = u.id) as order_count, (SELECT SUM (total) FROM orders WHERE user_id = u.id) as total_amountFROM users uWHERE u.status = 1 ;SELECT u.name, COUNT (o.id) as order_count, COALESCE (SUM (o.total), 0 ) as total_amountFROM users uLEFT JOIN orders o ON u.id = o.user_idWHERE u.status = 1 GROUP BY u.id, u.name;ALTER TABLE orders ADD INDEX idx_user_status (user_id, status);
六、索引优化 6.1 选择合适的列 1 2 3 4 5 6 7 8 9 10 11 12 WHERE age = 25 ORDER BY created_atON user_id = id
6.2 复合索引 1 2 3 4 5 6 7 8 9 10 11 ALTER TABLE orders ADD INDEX idx_status_date (status, created_at);WHERE status = 1 WHERE status = 1 AND created_at > '2026-01-01' WHERE created_at > '2026-01-01' AND status = 1 WHERE created_at > '2026-01-01'
6.3 索引覆盖 1 2 3 4 5 6 7 8 9 ALTER TABLE users ADD INDEX idx_age_name (age, name);SELECT name, age FROM users WHERE age = 25 ;SELECT * FROM users WHERE age = 25 ;
七、优化配置 7.1 关键配置参数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [mysqld] max_connections = 200 innodb_buffer_pool_size = 1 Ginnodb_log_file_size = 256 Minnodb_flush_log_at_trx_commit = 2
7.2 查看性能 1 2 3 4 5 6 7 8 9 10 11 12 13 14 SHOW PROCESSLIST;SHOW STATUS LIKE 'Qcache%' ;SHOW STATUS LIKE 'Threads%' ;SHOW TABLE STATUS FROM database_name;SHOW INDEX FROM table_name;
八、常见问题 8.1 查询突然变慢 1 2 3 4 5 6 7 8 9 10 11 SHOW ENGINE INNODB STATUS;SHOW FULL PROCESSLIST; ANALYZE TABLE table_name;SHOW ENGINE INNODB STATUS;
8.2 CPU使用率高 1 2 3 4 5 6 7 8 9 10 11 SHOW PROCESSLIST;SET GLOBAL slow_query_log = 'ON' ; EXPLAIN SELECT ...ALTER TABLE ...
九、工具推荐
工具
说明
mysqldumpslow
慢查询日志分析
EXPLAIN
SQL执行计划分析
SHOW PROFILE
性能分析
Performance Schema
性能监控
pt-query-digest
Percona工具
十、优化口诀 1 2 3 4 5 6 7 8 9 10 11 12 13 ┌─────────────────────────────────────────────────────────────────┐ │ SQL 优化口诀 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 1. 索引建立要趁早,WHERE 条件不能少 │ │ 2. 模糊查询尽量少,最左前缀要记牢 │ │ 3. 排序字段建索引,SELECT 只取需要的 │ │ 4. 分页大OFFSET ,改为游标或ID │ │ 5. JOIN 要小表驱动,复合索引最左走 │ │ 6. 慢查询日志开,分析工具来帮忙 │ │ 7. EXPLAIN 细细看,type 要达到ref 以上 │ │ │ └─────────────────────────────────────────────────────────────────┘
参考资料
持续更新中…欢迎收藏!
#MySQL #SQL优化 #性能优化 #EXPLAIN #教程