MySQL SQL 优化实战
TIP
SQL 优化是数据库性能调优的核心。良好的 SQL 写法可以指数级提升查询性能。
避免 SELECT *
sql
-- ❌ 坏习惯:查询所有列
SELECT * FROM user WHERE age > 18;
-- ✅ 只查需要的列
SELECT id, name, age FROM user WHERE age > 18;合理使用索引
sql
-- ❌ 索引列上使用函数
SELECT * FROM user WHERE DATE(created_at) = '2024-01-01';
-- ✅ 改为范围查询(走索引)
SELECT * FROM user WHERE created_at >= '2024-01-01' AND created_at < '2024-01-02';避免隐式类型转换
sql
-- ❌ phone 是 VARCHAR 类型
SELECT * FROM user WHERE phone = 1234567890; -- 不走索引
-- ✅ 使用字符串
SELECT * FROM user WHERE phone = '1234567890'; -- 走索引优化分页查询
sql
-- ❌ 传统分页(大偏移量时性能差)
SELECT * FROM user ORDER BY id LIMIT 100000, 10;
-- ✅ 子查询优化(利用索引覆盖)
SELECT * FROM user
WHERE id > (SELECT id FROM user ORDER BY id LIMIT 100000, 1)
ORDER BY id
LIMIT 10;
-- ✅ 记录上次最大值(适合滚动分页)
SELECT * FROM user WHERE id > 100000 ORDER BY id LIMIT 10;优化 JOIN
sql
-- ✅ 小表驱动大表
-- 假设 user 表 100 行,order 表 10000 行
SELECT u.*, o.order_amount
FROM user u
INNER JOIN order o ON u.id = o.user_id -- user 驱动 order
-- ✅ JOIN 字段要有索引
CREATE INDEX idx_user_id ON `order`(user_id);使用 EXISTS 代替 IN
sql
-- ❌ IN 子查询
SELECT * FROM user WHERE id IN (
SELECT user_id FROM order WHERE amount > 1000
);
-- ✅ EXISTS(子查询不会全表扫描)
SELECT * FROM user u WHERE EXISTS (
SELECT 1 FROM `order` o WHERE o.user_id = u.id AND o.amount > 1000
);使用 UNION ALL 代替 UNION
sql
-- ❌ UNION 会去重排序(额外开销)
SELECT name FROM user
UNION
SELECT name FROM old_user;
-- ✅ UNION ALL 直接合并(如果不需要去重)
SELECT name FROM user
UNION ALL
SELECT name FROM old_user;