MySQL 哪些情况下索引会失效

本文探讨了MySQL中索引失效的四个关键情况:函数操作、隐式类型转换、字符编码转换和模糊搜索。学习如何避免这些因素以优化查询性能。

众所周知,MySQL索引是以B+树存储的,而且是否使用索引是由引擎决定的,当MySQL觉得走索引花费开销大时,反而会放弃走索引。

总结一下,哪些情况下会使索引失效:

  1. 对where条件中的字段进行了函数操作,比如month(t_modified)=7;
  2. 隐式类型转换,比如where id_card=111, id_card是varchar, 而输入是111,需要做类型转换。MySQL默认将字符串转换为整数。如果索引字段是整数,条件是字符串,则会将条件转换为整数,不会影响走索引
  3. 隐式字符编码转换。比如表A 时utf8,表B是 utfmb4,表A join 表B查询,导致连接的字段需要进行字符串编码转换,比如select * from trade_detail where CONVERT(traideid USING utf8mb4)=$L2.tradeid.value;

如果线上不允许更改表的字符串编码,就只能才有修改SQ 陕西干部培训 www.zjganxun.cn L的方式了

mysql> select d.* from tradelog l , trade_detail d where d.tradeid=CONVERT(l.tradeid USING utf8) and l.id=2;
4. 模糊搜索,目前只有LIKE 'aaa%' 这种可以用到索引,其他如LIKE %a%`用不了索引

总而言之,不要对索引字段做函数操作,可能会破坏索引值的有序性,因此优化器决定放弃走树搜索功能

### 三级标题:MySQL索引失效的常见原因和场景 在MySQL中,索引是提升查询性能的重要工具,但在某些特定场景下,即使存在合适的索引,查询也可能无法使用索引,从而导致性能下降。以下是常见的索引失效场景及其原因分析。 **LIKE操作符使用不当** 是导致索引失效的典型原因之一。当使用`LIKE`进行模糊查询时,如果模式以通配符`%`开头,例如`LIKE '%abc'`,MySQL将无法利用相关列上的索引。这是因为索引的结构决定了它只能高效地支持前缀匹配,而不能支持后缀或中间匹配。[^2] **使用否定条件** 也会导致索引失效。具体来说,当查询中包含`!=`、`<>`、`NOT IN`、`NOT LIKE`等否定操作符时,MySQL通常无法使用索引优化查询。例如,创建了一个`idx_status`索引后,查询`SELECT * FROM orders WHERE status != 'completed';`可能不会使用该索引。[^4] **OR连接无索引字段** 是另一个需要注意的情况。如果查询中的`OR`条件中有一部分没有索引支持,那么整个查询可能都无法使用索引。这是因为MySQL优化器在处理`OR`条件时,需要确保所有可能的匹配路径都得到正确的处理。[^3] **联合索引索引不完整** 或者 **最左索引缺失** 同样会导致索引失效。在定义联合索引时,如果查询条件没有包含联合索引中最左侧的列,则该索引可能不会被使用。这是因为联合索引的构建方式类似于字典目录,只有从最左边开始的列才能保证索引的有效性。[^3] 此外,**索引列参与运算** 或 **函数调用** 也会导致索引失效。如果查询条件中对索引列进行了运算或者调用了函数,MySQL通常无法直接使用索引来加速查询。例如,查询`SELECT * FROM table WHERE YEAR(date_column) = 2023;`可能不会使用`date_column`上的索引。 **未用到覆盖索引** 也是常见的问题之一。覆盖索引是指查询的所有列都包含在一个索引中,这样数据库可以直接从索引中获取所需数据,而无需回表查询。如果查询没有使用覆盖索引,即使存在其他相关索引,也可能导致性能下降。 **MySQL放弃使用索引** 的情况也时有发生,尤其是在查询优化过程中,当MySQL估计使用索引的成本高于全表扫描时,它可能会选择不使用索引。这种情况通常发生在表的数据量较小或者统计信息不准确的情况下。 最后,**查询类型错误** 也可能导致索引失效。例如,当查询条件中的数据类型与索引列的数据类型不匹配时,MySQL可能无法正确使用索引。[^3] 综上所述,了解这些索引失效的场景对于优化数据库性能至关重要。通过合理设计查询语句和数据库结构,可以有效避免这些问题,提高查询效率。 ```sql -- 示例:避免索引失效的查询 -- 假设有一个名为orders的表,其中status列上有索引idx_status -- 正确使用索引的方式 SELECT * FROM orders WHERE status = 'pending'; -- 错误使用索引的方式 SELECT * FROM orders WHERE status != 'completed'; ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值