【后端数据库】MySQL 索引生效/失效规则 + 核心原理

发布于:2025-08-31 ⋅ 阅读:(18) ⋅ 点赞:(0)

 SQL 优化的核心 —— 什么时候能“走索引”,什么时候会“失效”。整理一个索引生效/失效规则 + 核心原理的全景图,帮助彻底理解。


🔑 MySQL 索引使用的核心原理

MySQL 使用 B+Tree 索引(最常见),特点是:

  • 数据在磁盘上是 有序存储 的。

  • 查询时会从根节点到叶子节点 二分查找

  • 只有满足 有序性 的条件才能利用索引,否则会退化成全表扫描。

所以,判断 SQL 是否能走索引的关键就是:WHERE 条件是否能利用索引的有序性


✅ 典型场景:会走索引

1. 精确匹配(==, IN

SELECT * FROM user WHERE id = 100;   -- 主键索引
SELECT * FROM user WHERE email IN ('a@xx.com','b@xx.com'); -- 普通索引

👉 等值查询最友好,100%用到索引。


2. 范围查询(BETWEEN, >, <, >=, <=

SELECT * FROM orders WHERE create_time BETWEEN '2024-01-01' AND '2024-12-31';

👉 范围条件能利用索引的有序性。


3. 前缀匹配(LIKE 'abc%'

SELECT * FROM article WHERE title LIKE '优化%';

👉 因为能从 abc 开头定位,所以可走索引。


4. 复合索引(最左前缀原则)

CREATE INDEX idx_user_name_age ON user(name, age);

-- 能走索引:
SELECT * FROM user WHERE name = 'Tom';
SELECT * FROM user WHERE name = 'Tom' AND age = 20;

👉 使用复合索引时,必须从 最左字段开始连续使用


5. 覆盖索引 (Covering Index)

-- 索引: (user_id, create_time)
SELECT user_id, create_time FROM orders WHERE user_id = 10;

👉 查询列全部在索引里,不需要回表,效率更高。


❌ 索引失效场景:不会走索引

1. LIKE '%abc' / %abc% (左模糊)

SELECT * FROM article WHERE title LIKE '%优化';
SELECT * FROM article WHERE title LIKE '%优化%';

👉 无法确定开头位置,B+Tree 的有序性失效。


2. 索引列上做函数 / 运算

-- 函数
SELECT * FROM user WHERE YEAR(create_time) = 2024;

-- 运算
SELECT * FROM user WHERE id + 1 = 10;

👉 MySQL 不能用索引里的有序值,只能逐行计算 → 全表扫描。


3. 隐式类型转换

-- id 是 int,但传了字符串
SELECT * FROM user WHERE id = '100';

👉 会触发类型转换,导致索引失效。


4. 使用 OR(混合索引列 vs 非索引列)

-- status 有索引,age 没有
SELECT * FROM user WHERE status = 1 OR age = 20;

👉 部分条件没索引 → 可能导致索引失效。

(解决办法:把 OR 改成 UNION ALL


5. 复合索引未遵循“最左前缀”

CREATE INDEX idx_name_age ON user(name, age);

-- ❌ age 单独用不了索引
SELECT * FROM user WHERE age = 20;

6. 使用 !=<>NOT INNOT LIKE

SELECT * FROM user WHERE status != 1;
SELECT * FROM user WHERE email NOT LIKE 'a%';

👉 索引失效,大概率全表扫描。


7. 在索引字段上用 IS NULL / IS NOT NULL

  • IS NULL 可以走索引(但要看情况)。

  • IS NOT NULL 基本走不了索引。


📊 总结表:索引能不能走

SQL 场景 是否走索引 说明
= / IN 精确匹配 最高效
范围查询(BETWEEN, <, > 能利用索引有序性
LIKE 'abc%' 前缀匹配 从开头开始匹配
LIKE '%abc' / %abc% 破坏有序性
复合索引(遵循最左前缀) 必须从最左列开始
索引列上函数 / 运算 索引失效
隐式类型转换 字符串 vs 数字要注意
!=<>NOT IN 基本全表扫描
IS NULL ✅(可能) 能用,效果视情况
IS NOT NULL 通常不走索引
覆盖索引 查询字段全在索引里

🌟 核心记忆法

👉 索引利用的关键:有序性

  • 能从“开头”精准定位 → ✅ 走索引

  • 破坏有序性(函数、运算、模糊、NOT) → ❌ 索引失效



网站公告

今日签到

点亮在社区的每一天
去签到