当前位置: 首页 > news >正文

索引失效类型和原因--1.对索引列使用函数

(1)对索引列使用函数

索引失效

SELECT * FROM my_table WHERE LEFT(column1, 3) = 'abc';

索引有效

SELECT * FROM my_table WHERE column1 LIKE 'abc%';

2. 索引失效的详细原因

(1)LIKE '%abc' 失效

  • MySQL B+Tree 索引按照前缀匹配,必须从最左侧开始匹配。
  • 'abc%' 可以在索引中找到起点,然后顺序查找,索引有效。
  • '%abc' 需要扫描整个表,逐个计算匹配,索引失效。

(2)LEFT(column1, 3) = 'abc' 失效

  • 索引存的是完整列值,但 LEFT(column1, 3) 计算的是新值
  • MySQL 无法在索引中找到计算后的值,只能遍历整个表计算,导致索引失效。

为什么 LEFT(column1, 3) = 'abc' 会导致索引失效


1. MySQL 索引的工作原理

MySQL 的 B+Tree 索引按照列的原始值存储数据,索引的作用是帮助数据库快速找到目标数据,类似于字典的目录。

比如,我们有一个索引如下:

column1 原始值索引存储的内容
“abcdef”“abcdef”
“abcxyz”“abcxyz”
“xyzabc”“xyzabc”
“123abc”“123abc”

索引按照完整的字符串排序,所以如果你查询:

SELECT * FROM my_table WHERE column1 = 'abcdef';

MySQL 可以直接通过索引找到 'abcdef' 这个值,而不需要扫描整个表。


2. LEFT(column1, 3) = 'abc' 是如何执行的?

SELECT * FROM my_table WHERE LEFT(column1, 3) = 'abc';

这时 MySQL 需要先计算 LEFT(column1, 3),然后再比较。 但索引里存储的是完整的 column1 值,而索引不能直接存储 LEFT(column1, 3) 计算的结果

为什么索引无效?

MySQL 需要先对每一行的数据执行 LEFT(column1, 3) 计算,看看前三个字符是不是 'abc'。 但索引无法存储计算后的值,所以 MySQL 不能直接用索引找到结果,而是必须遍历所有数据(全表扫描)。索引失效的核心原因之一是 MySQL 找不到起始位置

为什么 LEFT(column1, 3) = 'abc' 找不到起始位置?
1. MySQL 索引是按 完整的 column1 排序的

B+Tree 索引本质上是一个有序结构,它存储的顺序如下(假设 column1 建立了索引):

column1存储在索引中的数据
“abc123”✅ 有索引
“abc456”✅ 有索引
“abcd789”✅ 有索引
“xyz000”✅ 有索引

索引的作用是:能否直接找到起点并高效扫描。 但 LEFT(column1, 3) = 'abc' 破坏了索引的顺序查找能力


👉 打个比方:

  • LIKE 'abc%' 就像是直接查字典,找到 “abc” 开头的单词,然后顺序翻页,很快就能查到。
  • LEFT(column1, 3) = 'abc' 相当于必须检查字典里的每个单词,把它前 3 个字母取出来对比,再决定是否符合,必须翻完整本字典,速度极慢。

3. 解决方案

. LIKE 'abc%' 可以找到索引起点

✅ 方法 :用 LIKE 替代 LEFT()

SELECT * FROM my_table WHERE column1 LIKE 'abc%';
  • MySQL 可以找到索引的起点(例如 “abc123”)。
  • 然后按索引顺序扫描匹配的行,直到遇到第一个不满足 LIKE 'abc%' 的值(例如 “xyz000”)。
  • 这样查询就非常快,索引是有效的。

✅ 这个查询能用索引,是因为它可以在 B+Tree 里找到第一个 abc 开头的值,然后顺序扫描。

为什么这样能用索引?

  • 'abc%' 直接匹配 前缀,MySQL 可以用索引 快速定位 'abc' 开头的数据,而不需要计算每一行的值。

总结

  1. MySQL 索引存的是完整的原始值,不存储计算后的值。
  2. 对索引列使用函数(如 LEFT(column1, 3))时,MySQL 不能利用索引,必须对每一行计算,导致全表扫描。
  3. 避免在 WHERE 里对索引列使用函数,改用 LIKE 'abc%' 或者创建一个额外的存储列加索引,提高查询效率。

相关文章:

  • Python第六章10:字符串操作练习题
  • 贪心算法(10)(java)跳跃游戏
  • Git 命令操作完全指南
  • Redis常用数据类型深度解析:从理论到最佳实践
  • 2025最新3个wordpress好用的主题
  • LeetCode热题100JS(64/100)第十二天|79|131|51|35|74
  • SpringCloud alibaba专题-第一章
  • Rust从入门到精通之精通篇:22.Unsafe Rust 详解
  • 【GL012】C++ 易混点二
  • 分布式架构-Spring技术如何能实现分布式事务
  • 如何解决Redis缓存异常问题(雪崩、击穿、穿透)
  • k8s存储介绍(三)valume概述与emptydir
  • Java基础 3.25
  • Git更改暂存 : Git Pull 错误的快速解决方法
  • LeetCode142环形链表
  • 代码随想录算法训练营第五十六天 | 108.冗余连接 109.冗余连接II
  • 代码随想录算法训练营第四十一天|买卖股票专题:121. 买卖股票的最佳时机、122.买卖股票的最佳时机II、123.买卖股票的最佳时机III
  • 质检LIMS系统在食品生产加工企业的应用 如何保证食品生产企业的安全
  • Unity2022发布Webgl2微信小游戏部分真机黑屏
  • pytorch小记(十五):pytorch中 交叉熵损失详解:为什么logits比targets多一个维度?
  • 百度的网址是什么呢/网站关键词排名手机优化软件
  • 岳阳网站建设方案/百度指数的主要用户是
  • 桂阳 网站建设/seo 技术优化