首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >mysql索引失效场景及解决方案

mysql索引失效场景及解决方案

原创
作者头像
RookieCyliner
修改2025-06-28 14:26:43
修改2025-06-28 14:26:43
7060
举报
文章被收录于专栏:mysqlmysql

MySQL 索引失效是数据库性能优化中常见的问题,理解索引失效的场景对于提升查询效率至关重要。以下是 MySQL 索引失效的常见场景及解决方案:

一、查询条件不满足最左匹配原则

场景:复合索引(a, b, c)在以下查询中失效:

代码语言:javascript
复制
-- 未从索引首列开始
SELECT * FROM table WHERE b = 1 AND c = 2;

-- 跳过中间列
SELECT * FROM table WHERE a = 1 AND c = 2;

解决方案

  • 确保查询条件从复合索引的最左列开始
  • 调整索引顺序以匹配常用查询模式

二、在索引列上使用函数或表达式

代码语言:javascript
复制
-- 使用函数
SELECT * FROM table WHERE YEAR(create_time) = 2023;

-- 使用表达式
SELECT * FROM table WHERE price * 1.1 > 100;

解决方案

代码语言:txt
复制
将计算移到查询条件右侧:sql

SELECT * FROM table WHERE create_time >= '2023-01-01' AND create_time < '2024-01-01'; SELECT * FROM table WHERE price > 100 / 1.1;

三、隐式类型转换导致索引失效

代码语言:javascript
复制
-- 字段类型为VARCHAR,但查询时未加引号
SELECT * FROM table WHERE phone = 13800138000;

-- 字段类型为INT,但查询时加了引号
SELECT * FROM table WHERE id = '123';

解决方案

  • 确保查询条件中的数据类型与字段类型一致
  • 使用EXPLAIN检查是否存在类型转换

四、使用 LIKE 通配符开头

代码语言:javascript
复制
SELECT * FROM table WHERE name LIKE '%keyword';

解决方案

代码语言:txt
复制
避免通配符开头,改用:sql
SELECT * FROM table WHERE name LIKE 'keyword%';
  • 若必须支持双向搜索,可考虑:
    • 全文索引(FULLTEXT)
    • 应用层预处理(如建立反向索引)

五、OR 条件导致索引失效

代码语言:javascript
复制
SELECT * FROM table WHERE a = 1 OR b = 2;

解决方案

代码语言:txt
复制
若a和b均有独立索引,可拆分为UNION:sql
SELECT * FROM table WHERE a = 1 UNION SELECT * FROM table WHERE b = 2;
  • (a, b)创建复合索引

六、索引字段参与 NULL 值比较

代码语言:javascript
复制
SELECT * FROM table WHERE column IS NULL;
SELECT * FROM table WHERE column IS NOT NULL;

解决方案

  • 若查询频繁,可为字段添加NOT NULL约束
代码语言:txt
复制
对IS NULL条件创建索引:sql
CREATE INDEX idx_column ON table (column);

七、范围查询导致后续索引列失效

场景:复合索引(a, b, c)在以下查询中bc索引失效:

代码语言:javascript
复制
SELECT * FROM table WHERE a > 1 AND b = 2 AND c = 3;

解决方案

代码语言:txt
复制
将等值条件前置:sql
SELECT * FROM table WHERE b = 2 AND a > 1 AND c = 3;
  • (b, a, c)创建复合索引

八、数据分布导致优化器选择全表扫描

场景

  • 索引选择性低(如性别字段)
  • 统计信息过时

解决方案

  • 执行ANALYZE TABLE更新统计信息
代码语言:txt
复制
使用FORCE INDEX强制使用索引:sql
SELECT * FROM table FORCE INDEX (idx_column) WHERE column = 'value';

九、覆盖索引未被正确使用

代码语言:javascript
复制
-- 复合索引 (a, b)
SELECT a, b FROM table WHERE a = 1; -- 覆盖索引有效
SELECT a, b, c FROM table WHERE a = 1; -- 覆盖索引失效

解决方案

  • 确保查询只包含索引列
  • 扩展索引包含c(a, b, c)

十、索引被禁用或损坏

场景

  • 索引被手动禁用
  • 索引文件损坏

解决方案

代码语言:txt
复制
启用索引:sql
ALTER TABLE table ENABLE KEYS;
代码语言:txt
复制
重建索引:sql
ALTER TABLE table DROP INDEX idx_column; ALTER TABLE table ADD INDEX idx_column (column);

十一、存储引擎限制

场景

  • MyISAM 不支持外键约束
  • InnoDB 在WHERE子句中对主键和唯一索引使用范围查询时会失效

解决方案

  • 了解存储引擎特性
  • 对 InnoDB 主键范围查询,考虑改用等值查询或分页优化

十二、索引优化建议

代码语言:txt
复制
使用 EXPLAIN 分析查询:
EXPLAIN SELECT * FROM table WHERE column = 'value';

  1. 避免冗余索引
    • 索引(a, b)包含了索引(a)
代码语言:txt
复制
定期维护索引:
ANALYZE TABLE table; -- 更新统计信息 OPTIMIZE TABLE table; -- 重建表和索引
代码语言:txt
复制
监控索引使用情况:
SHOW STATUS LIKE 'Handler_read%';

通过避免上述场景,合理设计索引,并结合EXPLAIN工具进行分析,可显著提升 MySQL 查询性能。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、查询条件不满足最左匹配原则
  • 二、在索引列上使用函数或表达式
  • 三、隐式类型转换导致索引失效
  • 四、使用 LIKE 通配符开头
  • 五、OR 条件导致索引失效
  • 六、索引字段参与 NULL 值比较
  • 七、范围查询导致后续索引列失效
  • 八、数据分布导致优化器选择全表扫描
  • 九、覆盖索引未被正确使用
  • 十、索引被禁用或损坏
  • 十一、存储引擎限制
  • 十二、索引优化建议
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档