3. 索引失效与优化
Q: 哪些情况会导致索引失效?
核心点在于,有没有破坏索引的有序性
1. 查询条件包含OR
WHERE id = 1 OR name = 'Alice' -- name无索引则全表扫描2. 隐式类型转换
WHERE phone = 13888888888 -- phone是varchar,发生类型转换,索引失效
WHERE phone = '13888888888' -- ✅ 正确写法3. LIKE通配符
WHERE name LIKE '%Alice%' -- ❌ 前缀%导致索引失效
WHERE name LIKE 'Alice%' -- ✅ 可以使用索引4. 联合索引不符合最左前缀
-- 索引: (a, b, c)
WHERE b = 1 AND c = 2 -- ❌ 跳过了 a,索引失效
WHERE a = 1 AND c = 2 -- ✅ 可以使用索引(部分)5. 在索引列上使用函数
WHERE YEAR(create_time) = 2024 -- ❌ 索引失效
WHERE create_time >= '2024-01-01' AND create_time < '2025-01-01' -- ✅6. 对索引列运算
WHERE age + 1 = 25 -- ❌ 索引失效
WHERE age = 24 -- ✅ 正确写法7. 使用不等于操作符
WHERE id != 1 -- ❌ 可能导致索引失效
WHERE id <> 1 -- ❌ 可能导致索引失效
WHERE id NOT IN (1,2,3) -- ❌ 可能导致索引失效8. IS NULL / IS NOT NULL
WHERE name IS NULL -- ❌ 可能导致索引失效
WHERE name IS NOT NULL -- ❌ 可能导致索引失效9. 连接查询字段编码不一致
左连接查询或者右连接查询关联的字段编码格式不一样,可能导致索引失效。
10. 优化器选择全表扫描
MySQL优化器估计使用全表扫描要比使用索引快,则不使用索引。
Q: 如何进行SQL优化?
慢SQL定位
慢查询日志
开启MySQL的慢查询日志,再通过一些工具比如mysqldumpslow去分析对应的慢查询日志,当然现在一般的云厂商都提供了可视化的平台。
服务监控
可以在业务的基建中加入对慢SQL的监控,常见的方案有字节码插桩、连接池扩展、ORM框架过程,对服务运行中的慢SQL进行监控和告警。
SQL优化方法
1. 避免不必要的列
-- ❌ 避免使用
SELECT * FROM users WHERE id = 1;
-- ✅ 只查询需要的列
SELECT name, email FROM users WHERE id = 1;2. 利用覆盖索引
InnoDB使用非主键索引查询数据时会回表,但是如果索引的叶节点中已经包含要查询的字段,那它没有必要再回表查询了。
3. 避免使用 != 或者 <> 操作符
这些操作符会导致索引失效,引起全表扫描。
4. 避免计算或隐式转换
包含计算或者隐式计算会导致索引失效,引起全表的扫描(包括类型的转换)。
5. 增加冗余字段减少连表查询
增加冗余字段可以减少大量的连表查询,因为多张表的连表查询性能很低,所以可以适当的增加冗余字段,以减少多张表的关联查询,这是以空间换时间的优化策略。
优化原则:使用
EXPLAIN 查看执行计划,关注 type 字段:const > ref > range > index > ALL