like查询后置% 索引竟然也失效

背景

昨天早上接到一个任务,查询某类商品,数据库用的是mysql,版本是5.6.37,es_product 表数据不多,两万多条。执行语句我简化了一下,类似下面的这条sql:

SELECT * FROM es_product WHERE goods_code LIKE 'meiju%';

goods_code是建了索引的,它的值是由类型名称拼音+’_’+编码组成(这里是导致后面问题的关键),索引类型Normal。
语句执行的很慢,我们看下它的执行计划是什么:

EXPLAIN
SELECT * FROM es_product WHERE goods_code LIKE 'meiju%'

在这里插入图片描述
正常情况下模糊查询%后置索引是有效的,%前置的话,会导致索引失效。

可能导致的原因

因为它的值是由类型名称拼音+’_’+编码组成,所以想到的就是字段值的区分度以及重复率,区分度太小或重复率过高会使索引失效,进而走全表扫描。

例如性别字段,它一般就男,女,这就不建议建立索引了,区分度大小了。

es_product 总的数据量:24426
meiju字符串长度为5,我们就来看看长度为5的字符串的重复率:
执行下面的sql:

SELECT (count(*) / 24426 ) percent,count(*) cnt,LEFT(goods_code,5) prefix
FROM es_product GROUP BY prefix ORDER BY percent DESC LIMIT 0,10

在这里插入图片描述
可以看到,前缀为meiju的重复率竟然占到了0.268,区分度大小了,mysql选择了全表扫描。
我们来试试百分比为0.0135前缀为LEBAZ的执行计划
在这里插入图片描述
type=range,索引范围扫描。由此可见当重复率高到某个百分比值时,mysql会走全表扫描
后面我继续增大LEFT(str,length)函数中截取的length的大小,观察重复率。
在这里插入图片描述
在索引生效的情况,取到了本次实验重复率的最大值0.1022,前缀为liber-V,长度是7,
我们来看下它的执行计划:
在这里插入图片描述

解决

因为我这边要查的就是某类商品,如果用googs_code(类型名拼音+%)去查,重复率肯定会蛮高,然后就是导致索引失效,问了下同事,可以用别的表关联也可以查出某类商品,避开goods_code。

总结

通过这个例子,我们应该明白了,把类型拼音和编码放到一个字段里面也确实有问题,这样放也是为了查询某类商品是方便,但是这样也导致了用模糊查询大概率会导致索引失效,字段值的重复率过高会导致索引失效,我们没法保证查询前缀的值是什么,应当尽量去保证索引列高的区分度以及低的重复率。

<think>好的,我现在需要帮助用户理解MySQL索引的类型以及为什么在使用LIKE%开头时索引失效。首先,我应该回顾用户提供的引用内容,看看哪些信息可以直接应用。用户提到了几个引用,包括LIKE%开头导致索引失效的原因、覆盖索引的解决方法,以及隐式类型转换导致索引失效的情况。此外,用户还提到了之前的回答中关于事务并发控制的内容,但当前问题集中在索引类型和LIKE查询上,所以需要专注于这部分。 首先,关于索引类型,用户想知道MySQL有哪些种类。常见的索引类型包括主键索引、唯一索引、普通索引、全文索引、组合索引等。需要逐一解释每种索引的特点和用途,确保覆盖全面,同时结合用户提到的覆盖索引的情况,可能需要详细说明组合索引的结构和优势。 接下来是LIKE%开头导致索引失效的原因。根据引用[1]、[3]、[4],当LIKE模式以%开头时,比如'%abc',MySQL无法有效使用索引,因为索引是按照最左前缀匹配的。B+树索引的结构决定了只能从左边开始匹配,如果左边是通配符,就无法利用索引的有序性,导致全表扫描。需要详细解释B+树的结构,以及为什么左模糊匹配会破坏索引的有效性。 然后,用户还提到了索引失效的其他原因,比如隐式类型转换(引用[2]),虽然用户的问题中没有直接问这个,但可能需要简要提及,以展示对索引失效原因的全面理解,但重点还是放在LIKE的情况。 用户可能的需求不仅仅是了解现象,还想知道如何解决这类问题。根据引用[3],覆盖索引可以在某些情况下解决LIKE%开头导致索引失效的问题,所以需要解释覆盖索引的原理,即当查询的字段都包含在索引中时,即使索引无法高效查找,也可以避免回表,从而提升性能。此外,可以提到全文索引作为另一种解决方案,特别是对于文本搜索,但需要注意适用场景和配置。 需要确保回答结构清晰,分点列出索引类型,然后详细解释LIKE的问题,最后给出解决方案。同时,引用用户提供的参考资料,正确标注引用标记,例如[^1]、[^3]、[^4]等,以增强回答的可信度。 还需要注意用户可能的深层需求,比如如何优化查询性能,避免索引失效,因此在回答中可以加入实际示例,比如创建覆盖索引的SQL语句,或者使用全文索引的示例,帮助用户更好地理解和应用。 最后,生成的相关问题需要与主题紧密相关,帮助用户进一步探索,例如覆盖索引的具体应用、全文索引的使用场景,以及如何排查索引失效的其他原因等。</think>### MySQL索引类型与LIKE%开头索引失效详解 --- #### 一、MySQL索引类型及特点 | 索引类型 | 特点 | 适用场景 | |----------------|----------------------------------------------------------------------|------------------------------| | **主键索引** | 唯一且非空,表的主键自动成为主键索引 | 快速定位唯一记录(如ID查询) | | **唯一索引** | 列值唯一但允许NULL,加速查询并约束唯一性 | 唯一性校验(如邮箱、手机号) | | **普通索引** | 无唯一性约束,仅加速查询 | 高频查询字段(如商品名称) | | **组合索引** | 多列联合索引,遵循**最左前缀原则** | 多条件联合查询 | | **全文索引** | 基于分词技术,支持文本内容的关键词搜索(仅InnoDB和MyISAM支持) | 大文本模糊匹配(如文章搜索) | | **覆盖索引** | 索引包含查询所需的所有字段,无需回表查询[^3] | 提升查询性能 | **示例:组合索引的使用** ```sql -- 创建组合索引(name, age) CREATE INDEX idx_name_age ON users(name, age); -- 有效查询(使用索引) SELECT * FROM users WHERE name = 'Alice' AND age = 25; -- 部分有效(仅使用name字段索引) SELECT * FROM users WHERE name = 'Alice'; -- 无效查询(不满足最左前缀) SELECT * FROM users WHERE age = 25; ``` --- #### 二、LIKE%开头导致索引失效的原因 ##### 1. **B+树索引结构限制** MySQL索引基于B+树实现,其**有序性**要求查询条件必须从索引的最左端开始匹配。 - **有效场景**:`LIKE 'abc%'`(左固定,右模糊) - 索引可逐层定位到前缀为`abc`的节点,快速过滤数据[^1]。 - **失效场景**:`LIKE '%abc'`或`LIKE '%abc%'`(左模糊或全模糊) - 无法确定起始点,需全表扫描所有索引条目[^1][^4]。 ##### 2. **覆盖索引的优化方案** 若查询字段完全包含在索引中(覆盖索引),即使无法使用索引过滤数据,也可避免回表操作,提升性能[^3]。 ```sql -- 创建覆盖索引(name, id) CREATE INDEX idx_name_id ON users(name, id); -- 查询示例(无需回表) SELECT id FROM users WHERE name LIKE '%Alice%'; ``` ##### 3. **全文索引替代方案** 对于高频的模糊查询需求,可使用**全文索引**优化性能: ```sql -- 创建全文索引 ALTER TABLE articles ADD FULLTEXT INDEX ft_content(content); -- 全文搜索查询 SELECT * FROM articles WHERE MATCH(content) AGAINST('MySQL optimization'); ``` --- #### 三、其他常见索引失效场景(补充) 1. **隐式类型转换**: 字段类型与查询条件类型不一致时(如字符串字段用数字查询),索引失效[^2]。 ```sql -- 失效示例(varchar_column为字符串类型) SELECT * FROM table WHERE varchar_column = 123; ``` 2. **函数或表达式操作索引列**: 对索引列使用函数或运算(如`WHERE YEAR(create_time) = 2023`)会导致索引失效。 --- ### 总结:LIKE%开头索引失效的本质 1. **索引结构限制**:B+树无法支持左模糊匹配的快速定位。 2. **优化方向**: - 优先使用覆盖索引减少回表开销[^3]。 - 对文本搜索场景改用全文索引。 3. **设计原则**:避免在频繁查询的字段上使用左模糊匹配,必要时调整数据存储方式(如逆序存储)。 --- ### 相关问题 1. 如何通过覆盖索引优化`LIKE '%abc%'`查询? 2. 全文索引与普通模糊查询的性能差异有多大? 3. 隐式类型转换导致索引失效如何排查?
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值