-- 创建组合索引 CREATE INDEX idx_name_age ON users(name, age, city);
-- 有效使用索引 SELECT*FROM users WHERE name ='张三'; -- 使用第1列 SELECT*FROM users WHERE name ='张三'AND age =20; -- 使用第1、2列 SELECT*FROM users WHERE name ='张三'AND city ='北京'; -- 使用第1列
-- 无效使用索引 SELECT*FROM users WHERE age =20; -- 缺少第1列 SELECT*FROM users WHERE city ='北京'; -- 缺少第1列 SELECT*FROM users WHERE age =20AND city ='北京'; -- 缺少第1列
覆盖索引(Covering Index):
1 2 3 4 5 6
-- 创建覆盖索引 CREATE INDEX idx_name_email ON users(name, email);
-- 查询使用覆盖索引,无需回表 SELECT name, email FROM users WHERE name ='张三'; -- Extra列显示:Using index
索引选择性:
1 2 3 4 5 6 7 8
-- 计算选择性 SELECT COUNT(DISTINCT column_name) /COUNT(*) AS selectivity FROM table_name;
-- 5. 避免在WHERE子句中对字段进行表达式操作 -- 错误写法: SELECT*FROM users WHERE age *2=40; -- 正确写法: SELECT*FROM users WHERE age =20;
2.2 WHERE优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
-- 6. 使用IN替代OR(少量值时) SELECT*FROM users WHERE id IN (1, 2, 3);
-- 7. 使用EXISTS替代IN(子查询返回大量数据时) -- 使用EXISTS SELECT*FROM users u WHEREEXISTS (SELECT1FROM orders o WHERE o.user_id = u.id);
-- 8. 避免使用!=或<>操作符 -- 考虑使用范围查询或UNION代替
-- 9. 避免使用NULL判断 -- 错误写法: SELECT*FROM users WHERE name ISNULL; -- 优化方案:为列设置默认值
-- 10. 使用BETWEEN替代IN(范围查询) SELECT*FROM users WHERE age BETWEEN18AND30;
2.3 JOIN优化
1 2 3 4 5 6 7 8 9 10 11 12
-- 11. 确保JOIN列有索引 -- 12. 小表驱动大表 -- 错误写法(大表驱动): SELECT*FROM big_table b JOIN small_table s ON b.id = s.id; -- 正确写法(小表驱动): SELECT*FROM small_table s JOIN big_table b ON s.id = b.id;
-- 13. 避免JOIN过多表(建议不超过3个) -- 14. 使用STRAIGHT_JOIN强制连接顺序 SELECT STRAIGHT_JOIN *FROM table1 t1 JOIN table2 t2 ON t1.id = t2.id JOIN table3 t3 ON t2.id = t3.id;
-- 17. GROUP BY优化 -- 错误写法: SELECT category, COUNT(*) FROM products GROUPBY category; -- 优化方案:创建(category)索引
-- 18. 使用松散索引扫描 SELECTDISTINCT category FROM products;
2.5 子查询优化
1 2 3 4 5 6 7 8 9 10 11 12 13
-- 19. 将子查询转换为JOIN -- 原始写法: SELECT*FROM users WHERE id IN (SELECT user_id FROM orders); -- 优化写法: SELECTDISTINCT u.*FROM users u JOIN orders o ON u.id = o.user_id;
-- 20. 使用派生表优化 SELECT*FROM ( SELECT user_id, COUNT(*) as order_count FROM orders GROUPBY user_id ) t WHERE t.order_count >10;