-- 以下几种写法性能基本相同 SELECTCOUNT(*) FROM orders; SELECTCOUNT(1) FROM orders; SELECTCOUNT(id) FROM orders; -- 如果id可能为NULL,结果可能不同
案例三:JOIN优化
问题场景
1 2 3 4 5 6 7 8
-- 多表关联查询 SELECT o.*, u.name, p.product_name FROM orders o LEFTJOIN users u ON o.user_id = u.id LEFTJOIN products p ON o.product_id = p.id WHERE o.created_at >='2020-01-01' ORDERBY o.created_at DESC LIMIT 100;
优化方案
1. 确保关联字段有索引
1 2 3 4
-- 检查并添加索引 ALTER TABLE orders ADD INDEX idx_user_id (user_id); ALTER TABLE orders ADD INDEX idx_product_id (product_id); ALTER TABLE orders ADD INDEX idx_created_at (created_at);
2. 小表驱动大表
MySQL优化器通常会自动选择,但可以使用STRAIGHT_JOIN强制指定驱动表顺序。
1 2 3 4
SELECT STRAIGHT_JOIN o.*, u.name FROM users u INNERJOIN orders o ON o.user_id = u.id WHERE u.id =123;
3. 避免在关联字段上使用函数
1 2 3 4 5 6 7
-- 错误示例,索引失效 SELECT*FROM orders o JOIN users u ONCAST(o.user_id ASCHAR) = u.id;
-- 正确做法 SELECT*FROM orders o JOIN users u ON o.user_id = u.id;
案例四:ORDER BY优化
问题场景
1 2
-- Extra显示Using filesort SELECT*FROM orders WHERE user_id =123ORDERBY created_at DESC;
优化方案
创建复合索引
1 2
-- 让ORDER BY也能使用索引 ALTER TABLE orders ADD INDEX idx_user_created (user_id, created_at);
注意事项:
索引列的顺序要与ORDER BY一致
升序/降序要一致(MySQL 8.0支持降序索引)
多列排序时,所有列的排序方向要一致
案例五:GROUP BY优化
问题场景
1 2 3 4
-- 统计每个用户的订单数 SELECT user_id, COUNT(*) as order_count FROM orders GROUPBY user_id;
优化方案
1. 添加索引
1
ALTER TABLE orders ADD INDEX idx_user_id (user_id);
2. 使用松散索引扫描
当GROUP BY的列是索引的最左前缀时,MySQL可以使用松散索引扫描,效率更高。
3. 避免排序
1 2 3 4 5
-- 如果不需要排序,可以禁用 SELECT user_id, COUNT(*) as order_count FROM orders GROUPBY user_id ORDERBYNULL;
实用优化技巧
1. 批量操作
1 2 3 4 5 6 7
-- 避免逐条插入 INSERT INTO orders (user_id, amount) VALUES (1, 100); INSERT INTO orders (user_id, amount) VALUES (2, 200);