MySQL SELECT 查询性能优化指南
1. 索引优化
1.1 正确使用索引
- 在WHERE和ORDER BY涉及的列上建立索引
- 使用复合索引时遵循最左前缀原则
- 避免在索引列上使用函数或运算,会导致索引失效
-- 好的做法
SELECT * FROM users WHERE username = 'john'; -- username有索引
-- 不好的做法
SELECT * FROM users WHERE UPPER(username) = 'JOHN'; -- 函数导致索引失效
1.2 避免索引失效的情况
- 避免使用SELECT *
- 避免使用!=或<>操作符
- 避免在字段开头使用通配符(like ‘%abc’)
- 避免对索引字段进行运算
2. 查询优化
2.1 限制结果集大小
-- 使用 LIMIT 限制返回行数
SELECT * FROM large_table LIMIT 100;
-- 分页查询优化
SELECT * FROM large_table WHERE id > last_id LIMIT 20; -- 比 OFFSET 效率高
2.2 只查询需要的列
-- 好的做法
SELECT id, name FROM users;
-- 避免
SELECT * FROM users;
2.3 使用覆盖索引
- 尽量使查询的列都在索引中,避免回表查询
-- 假设有索引(name, age)
SELECT name, age FROM users WHERE name = 'John'; -- 使用覆盖索引
3. JOIN优化
3.1 JOIN优化策略
- 小表驱动大表
- 在关联字段上建立索引
- 使用INNER JOIN代替LEFT JOIN(如果可能)
-- 好的做法
SELECT * FROM small_table s
INNER JOIN large_table l ON s.id = l.small_id;
3.2 避免多表JOIN
- 控制JOIN表的数量,一般不超过3个表
- 考虑是否可以拆分成多个简单查询
4. WHERE子句优化
4.1 条件顺序
- 将过滤性最强的条件放在最前面
- 将索引列的条件放在前面
-- 好的做法
SELECT * FROM users
WHERE status = 'active' -- 高选择性
AND created_at > '2023-01-01'; -- 低选择性
4.2 避免OR操作
- 使用OR可能导致索引失效
- 考虑使用UNION ALL替代OR
-- 替代OR的写法
SELECT * FROM users WHERE status = 'active'
UNION ALL
SELECT * FROM users WHERE status = 'pending';
5. 其他优化技巧
5.1 使用EXPLAIN分析查询
EXPLAIN SELECT * FROM users WHERE status = 'active';
关注以下指标:
- type:访问类型(const最好,ALL最差)
- key:使用的索引
- rows:扫描的行数
5.2 合理使用子查询
- 尽量使用JOIN代替子查询
- 必要时使用临时表存储中间结果
5.3 缓存优化
- 使用应用层缓存(如Redis)
- 缓存常用查询结果
- 合理设置查询缓存大小
6. 配置优化
6.1 重要配置参数
- innodb_buffer_pool_size:缓冲池大小
- innodb_log_file_size:日志文件大小
- max_connections:最大连接数
6.2 硬件优化
- 使用SSD存储
- 增加内存容量
- 优化磁盘I/O配置
最佳实践总结
- 合理使用索引
- 只查询必要的数据
- 优化JOIN操作
- 定期使用EXPLAIN分析查询
- 进行查询语句重写
- 利用缓存机制
- 定期维护优化数据库配置