随着数据量增长,MySQL 查询性能可能成为系统瓶颈。本文通过真实案例,讲解如何发现慢查询、分析执行计划、优化 SQL 和索引、使用分页技巧、缓存策略及参数调优,让数据库查询更快、更稳。
开启慢查询日志,捕获超过 1 秒的查询:
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;
SHOW VARIABLES LIKE 'slow_query_log';案例: 查询订单表,慢日志记录如下:
SELECT * FROM orders WHERE status='paid' AND created_at > '2025-01-01';问题:全表扫描,返回大量字段,耗时长。
使用 EXPLAIN 查看查询执行路径:
EXPLAIN SELECT * FROM orders WHERE status='paid' AND created_at > '2025-01-01';问题:type=ALL,全表扫描,key=NULL,索引未命中。
SELECT id, user_id, total FROM orders WHERE status='paid' AND created_at >= '2025-01-01';减少 I/O 和内存开销。
-- 不推荐
WHERE YEAR(created_at) = 2025
-- 优化
WHERE created_at >= '2025-01-01' AND created_at < '2026-01-01'CREATE INDEX idx_status_created ON orders(status, created_at);重新执行 EXPLAIN:
id | select_type | table | type | key | rows | Extra |
|---|---|---|---|---|---|---|
1 | SIMPLE | orders | ref | idx_status_created | 5000 | Using index |
改进效果:扫描行数由 100,000 降到 5,000,显著提升性能。
-- 原子查询
SELECT u.id, u.name,
(SELECT COUNT(*) FROM orders o WHERE o.user_id = u.id) AS order_count
FROM users u;
-- 优化为 JOIN + GROUP BY
SELECT u.id, u.name, COUNT(o.id) AS order_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id, u.name;效果:减少重复子查询,执行更快。
WITH active_users AS (
SELECT id, name FROM users WHERE status='active'
)
SELECT a.id, a.name, COUNT(o.id) AS order_count
FROM active_users a
LEFT JOIN orders o ON a.id = o.user_id
GROUP BY a.id, a.name;提高复杂查询可读性和执行效率。
SELECT id, name FROM users
WHERE id > 1000
ORDER BY id
LIMIT 20;避免 OFFSET 扫描前面所有行,提高大表分页效率。
应用层缓存:使用 Redis/Memcached 缓解热点数据压力。
预计算字段:将统计数据提前计算存储,减少实时聚合。
-- 预计算示例
ALTER TABLE users ADD COLUMN order_count INT DEFAULT 0;
-- 触发器或应用层更新 order_count控制事务大小,避免长事务锁表。
批量 INSERT/UPDATE 提升效率:
INSERT INTO users (name,email)
VALUES ('Tom','tom@example.com'), ('Lucy','lucy@example.com');CREATE TABLE orders (
id INT NOT NULL,
created_at DATE NOT NULL,
total DECIMAL(10,2),
...
) PARTITION BY RANGE (YEAR(created_at)*100+MONTH(created_at)) (
PARTITION p202501 VALUES LESS THAN (202502),
PARTITION p202502 VALUES LESS THAN (202503)
);按用户 ID 或地区分表,减小单表压力,提高查询性能。
调整 InnoDB Buffer Pool 大小,提高缓存命中率。
调整连接数、临时表大小、慢查询阈值。
定期执行:
ANALYZE TABLE users;
OPTIMIZE TABLE orders;优化点 | 优化前 | 优化后 | 提升效果 |
|---|---|---|---|
SELECT * → 指定字段 | 100,000 rows | 10,000 rows | 10x |
索引创建 | 全表扫描 | ref 索引扫描 | 20x |
子查询 → JOIN | 200ms | 50ms | 4x |
OFFSET 分页 | 2s | 0.05s | 40x |
数据仅作示例,实际效果取决于表结构和数据量。
MySQL 优化是系统工程,从 SQL 语句优化到索引策略,从分页优化到事务管理,从缓存到数据库参数调整,每一环节都可能成为性能提升的关键。通过持续监控和优化,你可以让数据库查询更高效、应用响应更快,为大数据应用打下坚实基础。
关注我,带你深挖更多 MySQL 优化实战技巧、执行计划分析和性能调优案例,让你的数据库性能全面升级!