跳至内容
3. 索引失效与优化

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