MYSQL like模糊查询,%在前面索引为什么会失效 (最左前缀底层原理)

本文详细解释了数据库索引的工作原理,特别是B+树结构如何支持高效查询。讨论了不同数据类型的索引排序方式,并深入分析了在进行模糊查询时,放置通配符的位置如何影响索引的有效利用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

还是要从索引的数据结构说起。

我们都知道,我们通常用的索引数据结构是B+树,而索引是有序排列的。

如果索引关键字的类型是Int 类型,索引的排列顺序如下:

数据只存放在叶子节点,而且是有序的排放。

如果索引关键字的类型是String类型,排列顺序如下:

可以看出,索引的排列顺序是根据比较字符串的首字母排序的,如果首字母相同,就根据比较第二个字母进行排序,以此类推。

我们在进行模糊查询的时候,如果把 % 放在了前面,最左的  n 个字母便是模糊不定的,无法根据索引的有序性准确的定位到某一个索引,只能进行全表扫描,找出符合条件的数据。

如:where like '%sme' 

因为最左是%,无法确定是哪一个字母,只能根据sme去全表扫描找到符合的数据。

模糊查询时,把 % 放在最左是违背了索引有序排列的规则,就会造成索引失效,进行全表扫描。

在使用联合索引时也是如此,如果违背了索引有序排列的规则,同样会造成索引失效,进行全表扫描。

示例:

表test有个组合索引为:(A,B,C)

 SELECT * FROM test WHERE A=1 and B =1 and C=1; 可以走索引;

 SELECT * FROM test WHERE A=1 and C =1 and B=1; 可以走索引;

....

where 条件中只要有A就会走索引。

SELECT A FROM test WHERE C =1 and B=1 ORDER BY A; 可以走索引

SELECT B FROM test WHERE C =1 and B=1 ORDER BY A; 可以走索引

SELECT C FROM test WHERE C =1 and B=1 ORDER BY A; 可以走索引

SELECT A,C FROM test WHERE C =1 and B=1 ORDER BY A; 可以走索引

。。。。

(上面使用了覆盖索引)

SELECT * FROM test WHERE C =1 and B=1 ORDER BY A; 不可以走索引

(可通过EXPLAIN查看是否走索引)

<think>好的,我现在要解决用户的问题:在SQL中对索引列执行LIKE模糊查询时是否会引发索引失效的问题,以及原因和解决方法。首先,我需要回顾一下关于SQL索引LIKE查询的知识。 根据用户提供的引用内容,比如引用[1]和[2],里面提到当使用LIKE时,%的位置会影响索引是否有效。例如,当%在开头或者两边都有时,索引失效,而只在结尾使用%索引有效。这可能和索引的结构有关,比如B树索引是按照前缀排序的,所以当模糊查询的前缀不确定时,数据库无法有效利用索引进行查找,只能全表扫描。 接下来需要确认索引失效的具体原因。根据引用[4],覆盖索引的概念,如果查询的列都在索引中,可能可以避免回表,从而优化查询。不过当LIKE的模式导致无法使用索引时,覆盖索引可能也不起作用。另外,引用[3]提到索引碎片和索引维护的问题,但这里可能和LIKE失效的关系不大,除非索引维护不当导致原本有效的索引也无法使用。 然后,用户的问题需要给出解决方法。引用[1]提到使用翻转函数加前模糊查询的方法,比如将字符串反转后存储,并建立反转后的索引,这样当查询以某个后缀结尾的时候,可以转化为前缀查询,从而利用索引。另外,覆盖索引(引用[4])也是一个解决方案,如果查询的列都在索引中,即使索引失效,可能还是可以通过全索引扫描来避免全表扫描,但效率可能不如直接使用索引高。 还有,引用[5]中提到的EXPLAIN命令的使用,可以帮助分析查询是否使用了索引,以及索引的使用情况。这在实际优化中是很重要的一步,需要检查执行计划,确认索引是否被正确使用。 另外,用户可能没有提到的其他解决方法,比如全文索引或者使用搜索引擎如Elasticsearch来处理更复杂的模糊查询需求。不过根据提供的引用,这些可能不在当前讨论范围内,但可以作为补充建议。 总结下来,回答的结构应该是先说明不同LIKE模式对索引的影响,然后分析原因,接着给出解决方法,包括使用特定%位置、覆盖索引、函数索引、全文索引等,并提到使用EXPLAIN进行验证。同时要注意引用中的内容,正确标注引用来源。</think>在SQL中使用LIKE模糊查询时,索引是否失效取决于查询模式的具体形式。以下是具体分析及解决方案: --- ### 一、索引失效的触发条件 1. **前模糊查询**:`LIKE '%keyword'` - 索引失效原因:B树索引按字段**前缀**有序存储,前模糊查询无法定位起始扫描点,导致全表扫描[^1][^2]。 - 示例:`WHERE uuid LIKE "%u"` 2. **全模糊查询**:`LIKE '%keyword%'` - 索引失效原因:无法利用索引树的有序性,即使字段包含在索引中,仍需遍历所有记录[^1]。 - 示例:`WHERE uuid LIKE "%u%"` 3. **后模糊查询**:`LIKE 'keyword%'` - **索引有效**:可通过索引前缀匹配快速定位数据范围,无需全表扫描[^1]。 - 示例:`WHERE uuid LIKE "u%"` --- ### 二、索引失效的深层原因 1. **B树索引结构限制** - 索引按字段值的**完整前缀**构建,模糊查询中通配符`%`位于左侧时,破坏了前缀匹配规则。 2. **查询字段未完全覆盖索引** - 若查询字段包含未建立索引的列,即使索引部分生效,仍需回表查询数据,降低效率[^4]。 --- ### 三、优化方法 #### 1. 调整查询模式 - **优先使用后模糊查询**:`LIKE 'keyword%'` 确保通配符`%`仅出现在右侧,直接利用索引前缀匹配特性。 #### 2. 使用覆盖索引 - **确保查询字段全部在索引中** 例如,对字段`(a, b)`建立联合索引,查询`SELECT a, b FROM table WHERE a LIKE 'k%'`时,可直接通过索引返回数据,无需回表[^4]。 #### 3. 函数索引优化前模糊查询 - **反转字符串 + 后模糊查询** 1. 新增反向字段(如`reverse_uuid`)并建立索引 ```sql ALTER TABLE t2 ADD reverse_uuid VARCHAR(32); UPDATE t2 SET reverse_uuid = REVERSE(uuid); CREATE INDEX idx_reverse_uuid ON t2(reverse_uuid); ``` 2. 查询时反转关键词 ```sql SELECT * FROM t2 WHERE reverse_uuid LIKE REVERSE('keyword') + '%'; ``` 此方法将前模糊查询转换为后模糊查询,利用索引加速。 #### 4. 使用全文索引(适用于复杂模糊查询) - **MySQL全文索引** 对文本字段建立全文索引,支持自然语言搜索和布尔模式搜索: ```sql ALTER TABLE articles ADD FULLTEXT(title, body); SELECT * FROM articles WHERE MATCH(title, body) AGAINST ('keyword'); ``` #### 5. 执行计划分析 - **使用`EXPLAIN`验证索引使用情况** 通过分析`key`列确认是否命中索引,`rows`列估算扫描行数,`Extra`列检查是否触发覆盖索引[^5]。 ```sql EXPLAIN SELECT SQL_NO_CACHE * FROM t2 WHERE uuid LIKE 'u%'; ``` --- ### 四、总结 | 查询模式 | 索引是否有效 | 优化方案 | |-------------------|--------------|------------------------------| | `LIKE 'keyword%'` | ✔️ 有效 | 直接使用索引 | | `LIKE '%keyword'` | ❌ 失效 | 反转字符串 + 函数索引 | | `LIKE '%keyword%'`| ❌ 失效 | 全文索引或覆盖索引 | ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丢了尾巴的猴子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值