跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
SQL算法

MySQL EXPLAIN 实战:6 种索引失效场景验证与优化

综述由AI生成MySQL EXPLAIN 命令用于分析查询执行计划。文章验证了六种常见索引失效场景:左模糊匹配、函数操作、表达式计算、隐式类型转换、联合索引非最左匹配及 OR 条件。通过创建测试表并对比 EXPLAIN 结果,展示了全表扫描情况,提供了右模糊、范围查询、类型一致、最左前缀原则及 IN/UNION 等优化方案,帮助提升数据库查询性能。

神经兮兮发布于 2026/3/16更新于 2026/4/2511 浏览

前置知识:在阅读本文之前,建议先了解 EXPLAIN 命令的基础知识。如果你还不熟悉 EXPLAIN,请先阅读《MySQL EXPLAIN 命令详解:SQL 查询性能分析与优化指南(基础篇)》。

索引是提升数据库查询性能的重要手段,但并不是所有查询都能有效利用索引。在实际开发中,我们经常遇到索引失效的情况,导致查询性能下降。本文将通过 EXPLAIN 命令,逐一验证 6 种常见的索引失效场景,并提供相应的优化建议。

本文将验证以下场景:

  • 场景 1:模糊匹配导致索引失效
  • 场景 2:函数操作导致索引失效
  • 场景 3:表达式计算导致索引失效
  • 场景 4:隐式类型转换导致索引失效
  • 场景 5:联合索引非最左匹配导致索引失效
  • 场景 6:WHERE 子句中的 OR 导致索引失效

一、创建测试表

为了准确验证每个场景,我们采用"按需创建索引"的方式,避免预先创建的索引影响验证结果。

-- 创建员工表(不创建索引,只保留主键)
CREATE TABLE employees (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100),
    age INT,
    phone VARCHAR(20),
    salary DECIMAL(10,2),
    department_id INT,
    hire_date DATE
);

-- 插入测试数据
INSERT INTO employees (name, age, phone, salary, department_id, hire_date)
VALUES('张三',25,'13800138001',8000.00,1,'2020-01-15'),
      ('李四',30,'13800138002',12000.00,2,'2019-06-20'),
      ('王五',28,'13800138003',9500.00,1,'2021-03-10'),
      ('赵六',35,'13800138004',,,),
      (,,,,,),
      (,,,,,),
      (,,,,,),
      (,,,,,),
      (,,,,,),
      (,,,,,);


 employees;


 INDEX  employees;
15000.00
3
'2018-11-05'
'钱七'
27
'13800138005'
10000.00
2
'2020-08-22'
'张伟'
32
'13800138006'
13000.00
1
'2019-04-18'
'李娜'
29
'13800138007'
11000.00
3
'2021-01-30'
'王芳'
26
'13800138008'
8500.00
2
'2020-12-01'
'赵强'
31
'13800138009'
14000.00
1
'2018-07-15'
'钱龙'
33
'13800138010'
16000.00
3
'2017-09-20'
-- 查看表结构
DESC
-- 查看索引(此时只有主键索引)
SHOW
FROM

在这里插入图片描述


二、场景 1:模糊匹配导致索引失效

2.1 问题分析

问题: 左模糊匹配(LIKE '%value')会导致索引失效

2.2 验证过程
-- 创建 name 列的索引
CREATE INDEX idx_name ON employees(name);

-- 1.1 左模糊匹配(索引失效)
EXPLAIN SELECT * FROM employees WHERE name LIKE '%张';
-- 结果:type = ALL, key = NULL(全表扫描,索引失效)

-- 1.2 左右模糊匹配(索引失效)
EXPLAIN SELECT * FROM employees WHERE name LIKE '%张%';
-- 结果:type = ALL, key = NULL(全表扫描,索引失效)

-- 1.3 右模糊匹配(索引生效)
EXPLAIN SELECT * FROM employees WHERE name LIKE '张%';
-- 结果:type = range, key = idx_name(使用索引范围扫描)

-- 1.4 精确匹配(索引生效)
EXPLAIN SELECT * FROM employees WHERE name = '张三';
-- 结果:type = ref, key = idx_name(使用索引查找)
2.3 结论

分别从左模糊查询和右模糊查询我们可以看出,左模糊查询会导致索引失效,查询使用的是全盘扫描。右模糊查询则是使用到了索引查询。

  • 左模糊(%value)和左右模糊(%value%)会导致索引失效
  • 右模糊(value%)和精确匹配可以使用索引
2.4 优化建议
  • 避免使用左模糊匹配
  • 考虑使用全文索引(FULLTEXT)
  • 使用搜索引擎(如 Elasticsearch)

优化示例:

-- 方案 1:使用右模糊
WHERE name LIKE '张%'

-- 方案 2:使用全文索引
ALTER TABLE employees ADD FULLTEXT INDEX ft_name (name);
EXPLAIN SELECT * FROM employees WHERE MATCH(name) AGAINST('张' IN NATURAL LANGUAGE MODE);

-- 方案 3:使用搜索引擎(如 Elasticsearch)
-- 适合复杂的全文搜索场景

全文索引


三、场景 2:函数操作导致索引失效

3.1 问题分析

问题: 对索引列使用函数会导致索引失效

3.2 验证过程
-- 创建 hire_date 列的索引
CREATE INDEX idx_hire_date ON employees(hire_date);

-- 2.1 使用 YEAR 函数(索引失效)
EXPLAIN SELECT * FROM employees WHERE YEAR(hire_date)=2020;
-- 结果:type = ALL, key = NULL(全表扫描,索引失效)

-- 2.2 使用 MONTH 函数(索引失效)
EXPLAIN SELECT * FROM employees WHERE MONTH(hire_date)=6;
-- 结果:type = ALL, key = NULL(全表扫描,索引失效)

-- 2.3 使用 UPPER 函数(索引失效)
EXPLAIN SELECT * FROM employees WHERE UPPER(name)='张三';
-- 结果:type = ALL, key = NULL(全表扫描,索引失效)

-- 2.4 优化:使用范围查询(索引生效)
EXPLAIN SELECT * FROM employees WHERE hire_date BETWEEN '2020-01-01' AND '2020-12-31';
-- 结果:type = range, key = idx_hire_date(使用索引范围扫描)
3.3 结论

对索引使用函数会导致索引失效

  • 对索引列使用函数会破坏索引的有序性,导致索引失效
  • 应将函数操作移到应用层或使用范围查询替代
3.4 优化建议
  • 避免在 WHERE 子句中对索引列使用函数
  • 将函数操作移到应用层处理
  • 使用计算列或生成列(MySQL 5.7+)

优化示例:

-- 方案 1:使用范围查询
WHERE hire_date BETWEEN '2020-01-01' AND '2020-12-31'

-- 方案 2:使用计算列(MySQL 5.7+)
ALTER TABLE employees ADD COLUMN hire_year INT GENERATED ALWAYS AS(YEAR(hire_date)) STORED;
CREATE INDEX idx_hire_year ON employees(hire_year);
WHERE hire_year = 2020

-- 方案 3:应用层处理
-- 在应用层计算好年份,然后查询
WHERE hire_date >= '2020-01-01' AND hire_date <= '2020-12-31'

四、场景 3:表达式计算导致索引失效

4.1 问题分析

问题: 对索引列进行表达式计算会破坏索引

4.2 验证过程
-- 创建 salary 和 age 列的索引
CREATE INDEX idx_salary ON employees(salary);
CREATE INDEX idx_age ON employees(age);

-- 3.1 索引列参与计算(索引失效)
EXPLAIN SELECT * FROM employees WHERE salary + 1000 > 10000;
-- 结果:type = ALL, key = NULL(全表扫描,索引失效)

-- 3.2 索引列参与计算(索引失效)
EXPLAIN SELECT * FROM employees WHERE age - 5 > 20;
-- 结果:type = ALL, key = NULL(全表扫描,索引失效)

-- 3.3 索引列参与计算(索引失效)
EXPLAIN SELECT * FROM employees WHERE salary * 1.1 > 10000;
-- 结果:type = ALL, key = NULL(全表扫描,索引失效)

-- 3.4 优化:将计算移到右边(索引生效)
EXPLAIN SELECT * FROM employees WHERE salary > 10000 - 1000;
-- 结果:type = range, key = idx_salary(使用索引范围扫描)

-- 3.5 优化:直接使用常量(索引生效)
EXPLAIN SELECT * FROM employees WHERE salary > 9000;
-- 结果:type = range, key = idx_salary(使用索引范围扫描)
4.3 结论
  • 索引列参与表达式计算会导致索引失效
  • 应将计算移到查询条件的右边或应用层
4.4 优化建议
  • 避免在 WHERE 子句中对索引列进行计算
  • 将计算移到应用层
  • 使用覆盖索引优化

优化示例:

-- 方案 1:将计算移到右边
WHERE salary > 10000 - 1000

-- 方案 2:应用层计算
-- 在应用层计算好阈值,然后查询
WHERE salary > 9000

-- 方案 3:使用覆盖索引
CREATE INDEX idx_salary_bonus ON employees(salary, bonus);
WHERE salary + bonus > 100000

五、场景 4:隐式类型转换导致索引失效

5.1 问题分析

问题: 当查询中数据类型与索引不匹配时,会导致索引失效

5.2 验证过程
-- 创建 phone 和 department_id 列的索引
CREATE INDEX idx_phone ON employees(phone);
CREATE INDEX idx_dept ON employees(department_id);

-- 4.1 字符串列使用数字查询(索引失效)
-- phone 是 VARCHAR 类型,使用数字查询会导致隐式转换
EXPLAIN SELECT * FROM employees WHERE phone = 13800138001;
-- 结果:type = ALL, key = NULL(全表扫描,索引失效)

-- 4.2 优化:使用字符串查询(索引生效)
EXPLAIN SELECT * FROM employees WHERE phone = '13800138001';
-- 结果:type = ref, key = idx_phone(使用索引查找)

-- 4.3 数字列使用字符串查询(索引可能生效)
-- department_id 是 INT 类型
EXPLAIN SELECT * FROM employees WHERE department_id = '1';
-- 结果:type = ref, key = idx_dept(MySQL 自动转换,索引可能生效)

-- 4.4 日期列使用字符串查询(索引生效)
EXPLAIN SELECT * FROM employees WHERE hire_date = '2020-01-15';
-- 结果:type = ref, key = idx_hire_date(使用索引查找)
5.3 结论
  • 字符串列使用数字查询会导致隐式类型转换,索引失效
  • 应确保查询条件的数据类型与字段类型一致
5.4 优化建议
  • 确保查询条件的数据类型与字段类型一致
  • 使用显式类型转换函数
  • 在应用层进行类型转换

优化示例:

-- 方案 1:使用正确的类型
WHERE phone = '13800138001'

-- 方案 2:使用显式类型转换
WHERE phone = CAST(13800138001 AS CHAR)

-- 方案 3:应用层类型转换
-- 在应用层将数字转换为字符串,然后查询
WHERE phone = '13800138001'

六、场景 5:联合索引非最左匹配导致索引失效

6.1 问题分析

问题: 联合索引的查询条件不符合最左前缀匹配原则

6.2 验证过程
-- 删除可能影响验证的单列索引
DROP INDEX IF EXISTS idx_name ON employees;
DROP INDEX IF EXISTS idx_age ON employees;
DROP INDEX IF EXISTS idx_dept ON employees;

-- 创建联合索引:idx_name_age_dept (name, age, department_id)
CREATE INDEX idx_name_age_dept ON employees(name, age, department_id);

-- 5.1 使用最左列(索引生效)
EXPLAIN SELECT * FROM employees WHERE name = '张三';
-- 结果:type = ref, key = idx_name_age_dept, key_len = 403
-- 使用了联合索引的第一列

-- 5.2 使用最左两列(索引生效)
EXPLAIN SELECT * FROM employees WHERE name = '张三' AND age = 25;
-- 结果:type = ref, key = idx_name_age_dept, key_len = 408
-- 使用了联合索引的前两列

-- 5.3 使用全部三列(索引生效)
EXPLAIN SELECT * FROM employees WHERE name = '张三' AND age = 25 AND department_id = 1;
-- 结果:type = ref, key = idx_name_age_dept, key_len = 412
-- 使用了联合索引的全部三列

-- 5.4 跳过最左列(索引失效)
EXPLAIN SELECT * FROM employees WHERE age = 25;
-- 结果:type = ALL, key = NULL(全表扫描,索引失效)

-- 5.5 跳过最左列(索引失效)
EXPLAIN SELECT * FROM employees WHERE department_id = 1;
-- 结果:type = ALL, key = NULL(全表扫描,索引失效)

-- 5.6 跳过最左列,使用后两列(索引失效)
EXPLAIN SELECT * FROM employees WHERE age = 25 AND department_id = 1;
-- 结果:type = ALL, key = NULL(全表扫描,索引失效)

-- 5.7 使用最左列和第三列(部分索引生效)
EXPLAIN SELECT * FROM employees WHERE name = '张三' AND department_id = 1;
-- 结果:type = ref, key = idx_name_age_dept, key_len = 403
-- 只使用了第一列 name,跳过了 age,department_id 未使用

-- 5.8 范围查询后的列不生效
EXPLAIN SELECT * FROM employees WHERE name = '张三' AND age > 25 AND department_id = 1;
-- 结果:type = range, key = idx_name_age_dept, key_len = 408
-- 只使用了前两列,department_id 未使用(因为 age 是范围查询)
6.3 最左前缀原则
  • 联合索引必须从最左边开始匹配
  • 可以跳过中间的列,但不能跳过最左边的列
  • 范围查询(>、<、BETWEEN、LIKE)后的列不生效
6.4 结论
  • 跳过最左列会导致索引失效
  • 范围查询(>、<、BETWEEN 等)后的列无法使用索引
  • 必须从最左边开始匹配
6.5 优化建议
  • 创建联合索引时,将选择性高的列放在前面
  • 根据查询模式设计索引
  • 考虑创建多个单列索引

优化示例:

-- 方案 1:遵循最左前缀原则
WHERE name = '张三' AND age = 25

-- 方案 2:创建单独的索引
CREATE INDEX idx_dept ON employees(department_id);
WHERE department_id = 1

-- 方案 3:根据查询模式设计索引
-- 如果经常按 age 查询,创建单独的 age 索引
CREATE INDEX idx_age ON employees(age);
WHERE age = 25

七、场景 6:WHERE 子句中的 OR 导致索引失效

7.1 问题分析

问题: 当查询中存在 OR 连接的条件时,可能影响索引利用

7.2 验证过程
-- 重新创建单列索引(场景 5 已删除)
CREATE INDEX idx_name ON employees(name);
CREATE INDEX idx_age ON employees(age);
CREATE INDEX idx_salary ON employees(salary);
CREATE INDEX idx_dept ON employees(department_id);

-- 6.1 OR 连接不同索引列(索引失效)
EXPLAIN SELECT * FROM employees WHERE name = '张三' OR age = 25;
-- 结果:type = ALL, key = NULL(全表扫描,索引失效)

-- 6.2 OR 连接不同索引列(索引失效)
EXPLAIN SELECT * FROM employees WHERE salary > 10000 OR department_id = 1;
-- 结果:type = ALL, key = NULL(全表扫描,索引失效)

-- 6.3 OR 连接同一索引列(索引生效)
EXPLAIN SELECT * FROM employees WHERE name = '张三' OR name = '李四';
-- 结果:type = range, key = idx_name(使用索引范围扫描)

-- 6.4 优化:使用 IN 代替 OR(索引生效)
EXPLAIN SELECT * FROM employees WHERE name IN('张三','李四');
-- 结果:type = range, key = idx_name(使用索引范围扫描)

-- 6.5 优化:使用 UNION 代替 OR(索引生效)
EXPLAIN SELECT * FROM employees WHERE name = '张三' UNION SELECT * FROM employees WHERE age = 25;
-- 结果:两个查询都使用索引
-- 第一个查询:type = ref, key = idx_name
-- 第二个查询:type = ref, key = idx_age

-- 6.6 OR 连接有索引列和无索引列(索引失效)
-- 删除 salary 索引
DROP INDEX idx_salary ON employees;
EXPLAIN SELECT * FROM employees WHERE name = '张三' OR salary > 10000;
-- 结果:type = ALL, key = NULL(全表扫描,索引失效)
-- 重新创建索引
CREATE INDEX idx_salary ON employees(salary);
7.3 结论
  • OR 连接不同索引列会导致索引失效
  • OR 连接同一索引列可以使用索引
  • 可以使用 IN 或 UNION 代替 OR
7.4 优化建议
  • 尽量使用 IN 代替 OR
  • 使用 UNION ALL 代替 OR(如果确定无重复)
  • 确保 OR 条件使用同一索引

优化示例:

-- 方案 1:使用 IN 代替 OR
WHERE name IN('张三','李四')

-- 方案 2:使用 UNION 代替 OR
SELECT * FROM employees WHERE name = '张三' UNION SELECT * FROM employees WHERE age = 25

-- 方案 3:使用 UNION ALL(如果确定无重复)
SELECT * FROM employees WHERE name = '张三' UNION ALL SELECT * FROM employees WHERE age = 25

八、索引失效场景总结表

场景示例 SQL索引状态type优化建议
左模糊匹配WHERE name LIKE '%张'失效ALL使用右模糊或全文索引
左右模糊匹配WHERE name LIKE '%张%'失效ALL使用右模糊或全文索引
右模糊匹配WHERE name LIKE '张%'生效range-
函数操作WHERE YEAR(hire_date) = 2020失效ALL使用范围查询
表达式计算WHERE salary + 1000 > 10000失效ALL计算移到右边
隐式类型转换WHERE phone = 13800138001失效ALL使用字符串类型
联合索引跳过最左列WHERE age = 25失效ALL遵循最左前缀原则
OR 连接不同索引列WHERE name = '张' OR age = 25失效ALL使用 UNION 或 IN

九、完整验证脚本

-- ========================================
-- 完整验证脚本:从头开始验证所有场景
-- ========================================
-- 1. 删除已存在的表(如果存在)
DROP TABLE IF EXISTS employees;

-- 2. 创建员工表(不创建索引)
CREATE TABLE employees (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100),
    age INT,
    phone VARCHAR(20),
    salary DECIMAL(10,2),
    department_id INT,
    hire_date DATE
);

-- 3. 插入测试数据
INSERT INTO employees (name, age, phone, salary, department_id, hire_date)
VALUES('张三',25,'13800138001',8000.00,1,'2020-01-15'),
      ('李四',30,'13800138002',12000.00,2,'2019-06-20'),
      ('王五',28,'13800138003',9500.00,1,'2021-03-10'),
      ('赵六',35,'13800138004',15000.00,3,'2018-11-05'),
      ('钱七',27,'13800138005',10000.00,2,'2020-08-22'),
      ('张伟',32,'13800138006',13000.00,1,'2019-04-18'),
      ('李娜',29,'13800138007',11000.00,3,'2021-01-30'),
      ('王芳',26,'13800138008',8500.00,2,'2020-12-01'),
      ('赵强',31,'13800138009',14000.00,1,'2018-07-15'),
      ('钱龙',33,'13800138010',16000.00,3,'2017-09-20');

-- ========================================
-- 场景 1:模糊匹配
-- ========================================
SELECT '========== 场景 1:模糊匹配 ==========' AS test_case;
CREATE INDEX idx_name ON employees(name);
SELECT '1.1 左模糊匹配(索引失效)';
EXPLAIN SELECT * FROM employees WHERE name LIKE '%张';
SELECT '1.2 左右模糊匹配(索引失效)';
EXPLAIN SELECT * FROM employees WHERE name LIKE '%张%';
SELECT '1.3 右模糊匹配(索引生效)';
EXPLAIN SELECT * FROM employees WHERE name LIKE '张%';
SELECT '1.4 精确匹配(索引生效)';
EXPLAIN SELECT * FROM employees WHERE name = '张三';

-- ========================================
-- 场景 2:函数操作
-- ========================================
SELECT '========== 场景 2:函数操作 ==========' AS test_case;
CREATE INDEX idx_hire_date ON employees(hire_date);
SELECT '2.1 使用 YEAR 函数(索引失效)';
EXPLAIN SELECT * FROM employees WHERE YEAR(hire_date)=2020;
SELECT '2.2 使用 MONTH 函数(索引失效)';
EXPLAIN SELECT * FROM employees WHERE MONTH(hire_date)=6;
SELECT '2.3 优化:使用范围查询(索引生效)';
EXPLAIN SELECT * FROM employees WHERE hire_date BETWEEN '2020-01-01' AND '2020-12-31';

-- ========================================
-- 场景 3:表达式计算
-- ========================================
SELECT '========== 场景 3:表达式计算 ==========' AS test_case;
CREATE INDEX idx_salary ON employees(salary);
CREATE INDEX idx_age ON employees(age);
SELECT '3.1 索引列参与计算(索引失效)';
EXPLAIN SELECT * FROM employees WHERE salary + 1000 > 10000;
SELECT '3.2 索引列参与计算(索引失效)';
EXPLAIN SELECT * FROM employees WHERE age - 5 > 20;
SELECT '3.3 优化:将计算移到右边(索引生效)';
EXPLAIN SELECT * FROM employees WHERE salary > 9000;

-- ========================================
-- 场景 4:隐式类型转换
-- ========================================
SELECT '========== 场景 4:隐式类型转换 ==========' AS test_case;
CREATE INDEX idx_phone ON employees(phone);
CREATE INDEX idx_dept ON employees(department_id);
SELECT '4.1 字符串列使用数字查询(索引失效)';
EXPLAIN SELECT * FROM employees WHERE phone = 13800138001;
SELECT '4.2 优化:使用字符串查询(索引生效)';
EXPLAIN SELECT * FROM employees WHERE phone = '13800138001';

-- ========================================
-- 场景 5:联合索引非最左匹配
-- ========================================
SELECT '========== 场景 5:联合索引非最左匹配 ==========' AS test_case;
-- 删除可能影响验证的单列索引
DROP INDEX idx_name ON employees;
DROP INDEX idx_age ON employees;
DROP INDEX idx_dept ON employees;
-- 创建联合索引
CREATE INDEX idx_name_age_dept ON employees(name, age, department_id);
SELECT '5.1 使用最左列(索引生效)';
EXPLAIN SELECT * FROM employees WHERE name = '张三';
SELECT '5.2 使用最左两列(索引生效)';
EXPLAIN SELECT * FROM employees WHERE name = '张三' AND age = 25;
SELECT '5.3 跳过最左列(索引失效)';
EXPLAIN SELECT * FROM employees WHERE age = 25;
SELECT '5.4 跳过最左列,使用后两列(索引失效)';
EXPLAIN SELECT * FROM employees WHERE age = 25 AND department_id = 1;

-- ========================================
-- 场景 6:OR 条件
-- ========================================
SELECT '========== 场景 6:OR 条件 ==========' AS test_case;
-- 重新创建单列索引
CREATE INDEX idx_name ON employees(name);
CREATE INDEX idx_age ON employees(age);
CREATE INDEX idx_salary ON employees(salary);
CREATE INDEX idx_dept ON employees(department_id);
SELECT '6.1 OR 连接不同索引列(索引失效)';
EXPLAIN SELECT * FROM employees WHERE name = '张三' OR age = 25;
SELECT '6.2 OR 连接同一索引列(索引生效)';
EXPLAIN SELECT * FROM employees WHERE name = '张三' OR name = '李四';
SELECT '6.3 优化:使用 IN 代替 OR(索引生效)';
EXPLAIN SELECT * FROM employees WHERE name IN('张三','李四');

-- ========================================
-- 验证完成
-- ========================================
SELECT '========== 验证完成 ==========' AS message;
SHOW INDEX FROM employees;

十、优化建议总结

10.1 模糊查询优化
-- 避免 WHERE name LIKE '%张%'
-- 推荐 WHERE name LIKE '张%'
-- 或使用全文索引 WHERE MATCH(name) AGAINST('张')
10.2 函数操作优化
-- 避免 WHERE YEAR(hire_date)=2020
-- 推荐 WHERE hire_date BETWEEN '2020-01-01' AND '2020-12-31'
10.3 表达式计算优化
-- 避免 WHERE salary + 1000 > 10000
-- 推荐 WHERE salary > 9000
10.4 类型转换优化
-- 避免(phone 是 VARCHAR 类型)WHERE phone = 13800138001
-- 推荐 WHERE phone = '13800138001'
10.5 联合索引优化
-- 联合索引:(name, age, department_id)
-- 避免 WHERE age = 25
-- 推荐 WHERE name = '张三' AND age = 25
10.6 OR 条件优化
-- 避免 WHERE name = '张三' OR age = 25
-- 推荐 WHERE name IN('张三','李四')
-- 或 SELECT * FROM employees WHERE name = '张三' UNION SELECT * FROM employees WHERE age = 25

十一、总结

通过 EXPLAIN 命令验证,我们确认了以下 6 种常见的索引失效场景:

  1. 模糊匹配:左模糊和左右模糊导致索引失效
  2. 函数操作:对索引列使用函数破坏索引有序性
  3. 表达式计算:索引列参与计算导致索引失效
  4. 隐式类型转换:数据类型不匹配导致索引失效
  5. 联合索引非最左匹配:跳过最左列导致索引失效
  6. OR 条件:OR 连接不同索引列导致索引失效

关键指标:

  • type = ALL:全表扫描,索引失效
  • key = NULL:未使用索引
  • type = ref/range:使用索引查找/范围扫描
  • key = idx_xxx:使用了指定索引

验证方法:

  • 采用"按需创建索引"的方式,避免预先创建的索引影响验证结果
  • 每个场景独立验证,确保结果准确
  • 提供完整的验证脚本,可以一键运行

通过合理使用 EXPLAIN,你可以对查询进行深入分析,找出性能瓶颈,从而提升数据库性能。

目录

  1. 一、创建测试表
  2. 二、场景 1:模糊匹配导致索引失效
  3. 2.1 问题分析
  4. 2.2 验证过程
  5. 2.3 结论
  6. 2.4 优化建议
  7. 三、场景 2:函数操作导致索引失效
  8. 3.1 问题分析
  9. 3.2 验证过程
  10. 3.3 结论
  11. 3.4 优化建议
  12. 四、场景 3:表达式计算导致索引失效
  13. 4.1 问题分析
  14. 4.2 验证过程
  15. 4.3 结论
  16. 4.4 优化建议
  17. 五、场景 4:隐式类型转换导致索引失效
  18. 5.1 问题分析
  19. 5.2 验证过程
  20. 5.3 结论
  21. 5.4 优化建议
  22. 六、场景 5:联合索引非最左匹配导致索引失效
  23. 6.1 问题分析
  24. 6.2 验证过程
  25. 6.3 最左前缀原则
  26. 6.4 结论
  27. 6.5 优化建议
  28. 七、场景 6:WHERE 子句中的 OR 导致索引失效
  29. 7.1 问题分析
  30. 7.2 验证过程
  31. 7.3 结论
  32. 7.4 优化建议
  33. 八、索引失效场景总结表
  34. 九、完整验证脚本
  35. 十、优化建议总结
  36. 10.1 模糊查询优化
  37. 10.2 函数操作优化
  38. 10.3 表达式计算优化
  39. 10.4 类型转换优化
  40. 10.5 联合索引优化
  41. 10.6 OR 条件优化
  42. 十一、总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • 💰 8折买阿里云服务器限时8折购买
  • 🦞 5分钟部署阿里云小龙虾了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • IT 项目管理那些事儿
  • 基于 AI 辅助开发的在线图书借阅平台设计与实现
  • Windows 10 本地部署 DataX 与 DataX-Web
  • 7D-AI系列:AI 编程 Spec Coding 完整详细的典型标准化工作流
  • Android Framework WMS 核心概述与知识要点
  • OpenDroneMap 无人机影像三维重建:安装部署与实战指南
  • Llama-2-7b 昇腾 NPU 测评:核心性能数据、场景适配与硬件选型
  • 主流 AI 大模型工具集合与功能介绍
  • 双指针算法详解:三数之和与四数之和
  • C++ 多态底层实现原理详解
  • 基于 Q-Learning 的无人机三维动态避障路径规划研究
  • 大模型算法二次开发:核心流程与关键技术详解
  • Spring Boot 后端开发核心注解详解
  • Python 集成 IPIDEA 网页抓取 API 实现 eBay 数据采集实战
  • 数据结构栈与队列基础及竞赛高频算法实操
  • FreeAskInternet:无需 GPU 的本地化大语言模型对话系统部署
  • Meta 提出多 token 模型训练新方法,有望提升生成速度与智能性
  • 基于 DeepSeek-R1-Distill-Llama-8B 的 OpenSpec 协议分析
  • 在 Claude Code 中快速接入 MiniMax 大模型
  • C# .NET Framework Web Service 开发实例详解

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • SQL 美化和格式化

    在线格式化和美化您的 SQL 查询(它支持各种 SQL 方言)。 在线工具,SQL 美化和格式化在线工具,online

  • SQL转CSV/JSON/XML

    解析 INSERT 等受限 SQL,导出为 CSV、JSON、XML、YAML、HTML 表格(见页内语法说明)。 在线工具,SQL转CSV/JSON/XML在线工具,online

  • CSV 工具包

    CSV 与 JSON/XML/HTML/TSV/SQL 等互转,单页多 Tab。 在线工具,CSV 工具包在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online