网站慢?可能是数据库拖后腿。这 5 个 MySQL 优化我屡试不爽
上个月有个朋友找我,说他的网站最近卡得不行,打开一个页面要等五六秒。
我帮他查了一圈,最后发现问题出在数据库上——有个查询语句没加索引,每次都要扫全表。加上索引后,查询从 3 秒变 30 毫秒。
这种问题我见过太多次了。今天分享的这 5 个优化技巧,都是我在实际项目中用过、确实有效的。
1. 索引别乱加,但该加的一定要加
索引这东西,就像字典的目录。没有目录,找东西只能一页一页翻;有了目录,一查就能定位。
我一般这么做:
-- 给常用查询字段加索引
ALTER TABLE users ADD INDEX idx_email (email);
ALTER TABLE orders ADD INDEX idx_created_at (created_at);
-- 复合索引注意顺序(区分度高的放前面)
ALTER TABLE orders ADD INDEX idx_user_status (user_id, status);
但索引不是越多越好。我见过有人给一个表加了十几个索引,结果写入速度慢得离谱。
怎么判断索引有没有用?用 EXPLAIN 看执行计划:
EXPLAIN SELECT * FROM users WHERE email = 'test@example.com';
如果 type 那一列显示 ALL,说明在全表扫描,赶紧加索引。如果是 ref 或者 range,说明索引生效了。
2. 慢查询日志一定要开
MySQL 自带慢查询日志,能帮你揪出那些拖后腿的 SQL。
配置方法:
# 编辑配置文件
sudo nano /etc/mysql/my.cnf
# 添加这些
[mysqld]
slow_query_log = 1
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time = 2 # 超过 2 秒的记录
重启 MySQL 后,所有超过 2 秒的查询都会记下来。定期看看这个日志,把排名靠前的 SQL 优化一下,效果立竿见影。
分析工具有 mysqldumpslow:
# 按查询时间排序,显示前 10 条
mysqldumpslow -s t -t 10 /var/log/mysql/mysql-slow.log
# 按返回记录数排序
mysqldumpslow -s r -t 10 /var/log/mysql/mysql-slow.log
3. 别再 SELECT * 了
这个我说过无数次,还是有人犯。
-- 错误写法
SELECT * FROM users WHERE id = 1;
-- 正确写法
SELECT id, username, email FROM users WHERE id = 1;
别小看这个区别。如果表里有 TEXT、BLOB 这种大字段,SELECT * 会把所有内容都读出来,浪费 IO 还占内存。
我有个项目,把 SELECT * 改成只查需要的字段后,页面加载时间从 2 秒降到了 0.5 秒。
4. JOIN 查询有讲究
多表查询很常见,但用不好就是性能杀手。
几个原则:
- 小表驱动大表(数据量小的表放左边)
- JOIN 的字段必须有索引
- 超过 3 张表的 JOIN,考虑拆开查询
-- 优化前(慢)
SELECT * FROM orders o
LEFT JOIN users u ON o.user_id = u.id
LEFT JOIN products p ON o.product_id = p.id
WHERE o.status = 'completed';
-- 优化后(快)
SELECT o.id, o.amount, u.username, p.name
FROM orders o
LEFT JOIN users u ON o.user_id = u.id
LEFT JOIN products p ON o.product_id = p.id
WHERE o.status = 'completed';
区别在于只查需要的字段,不浪费。
5. 定期维护不能懒
数据库用久了会产生碎片,定期维护能保持良好状态。
-- 优化表(回收碎片)
OPTIMIZE TABLE users;
OPTIMIZE TABLE orders;
-- 分析表(更新统计信息)
ANALYZE TABLE users;
我一般写个定时任务,每周日凌晨执行一次。
还有,旧数据及时清理:
-- 删除 30 天前的日志
DELETE FROM logs WHERE created_at < DATE_SUB(NOW(), INTERVAL 30 DAY);
-- 清理后优化表
OPTIMIZE TABLE logs;
最后说点实在的
上面这 5 个技巧,按优先级排序:
- 加索引:效果最明显,优先做
- 开慢查询日志:找到瓶颈
- **改 SELECT ***:养成好习惯
- 优化 JOIN:多表查询必备
- 定期维护:保持长期稳定
数据库优化不是一蹴而就的事。我建议你先把慢查询日志打开,跑一段时间,看看哪些 SQL 最慢,然后逐个优化。
对了,上面这些操作,建议先在测试环境试试。生产环境直接搞,出了问题我可不管啊。
本文提到的命令基于 MySQL 5.7/8.0,其他版本可能有差异。操作前建议备份数据。
