mysql索引失效场景总结


前言

mysql的调优方面包括 表结构优化、索引优化、sql语句优化、分表分库优化等多个维度,本篇重点总结的是索引失效的场景和原因。


写博客是自己对知识梳理,目前是写给自己看,算是自己学习后的作业,也是为了养成一个良好的习惯。

一、不满足最左匹配原则

先复习一下最左匹配原则:
	1. 创建一个联合索引 index(a,b,c) 则相对于创建了 idx_a(a)idx_a_b(a,b)idx_a_b_c(a,b,c) 3个索引。
	-------------------------------------------------------
	select * from table where a='a' and c='c';
	这种都之会走 idx_a索引,而 字段 c则不会走索引。
	-------------------------------------------------------
	select * from table where b='b' and c='c';
	这种会走全表扫描,index索引失效。
	-------------------------------------------------------

	2. 联合索引在遇到范围查询之后字段的索引就会失效。
	-------------------------------------------------------
	select * from table where a like 'a%' and b='b';
	这种会走idx_a索引的范围检索,字段b不会走索引。
	-------------------------------------------------------

二、频繁回表

	先来分析一下以下sql在mysql下是如何执行的:
	select * from table where age > 20 ; --其中 字段age 创建索引 
	会先在索引age字段的b+tree上查询到关于符合条件的id,然后在聚簇索引上通过id回表查询到完整数据。
	则select * 一定会有回表操作,当查询的结果超过了总数一半以上且总数很多时,这个时候回表开销比全表扫描的开销还大,则mysql优化器会它走全表扫描,即索引失效了。

三、索引列上有计算

	举例:select * from t_user where age+1=10;
	这种索引会直接失效。

四、索引列上有函数

	举例:select * from user where SUBSTR(height,1,2)=17;
	这种索引会直接失效。

五、字段类型不同

	举例:select * from user where type = '5';
	type是整数类型,查询时用字符串,mysql会做隐式转换,索引会直接失效。
	-------------------------------------------------------
	举例:select oi.*,ui.name from order_info oi left join user_info ui on oi.user_id = ui.id;
	其中order_info的user_id是字符串类型,user_info的id是整数类型,即便order_info的user_id创建索引也会由于字段类型不同而做隐式转换,索引会失效。

六、列对比

	举例:select * from user where id=height;
	列对比索引会直接失效。

七、常见索引失效

	诸如索引列 使用了 not in、 like ‘%x’ 、or 都会索引失效
<think>好的,我现在需要帮助用户总结MySQL索引失效的常见场景及原因。首先,我要回忆用户提供的引用内容,确保信息准确。用户提到了四个引用,涉及索引失效的不同情况,比如OR条件、范围查询后的失效、LIKE操作符的使用等。 首先,我应该整理这些引用中的关键点。引用[1]提到了索引失效的几种常见场景,但没有具体说明;引用[2]指出OR关键字导致失效的情况,特别是当其中一个字段没有索引或使用范围查询时;引用[3]提到范围查询后索引可能部分使用,但后续条件可能失效;引用[4]强调LIKE以通配符开头导致索引失效。 接下来,我需要将用户的问题结构化,分点说明常见的失效场景。每个场景需要包含原因和示例,这样用户更容易理解。例如,OR条件的情况,需要说明当OR连接的字段中有一个无索引时,整个查询会失效。或者使用LIKE以%开头时,无法利用索引,因为最左前缀原则。 同时,要注意用户提到的系统级指令,比如行内数学表达式用$...$,独立公式用$$...$$,但这个问题可能不需要数学公式,所以可能不需要使用。另外,用中文回答,结构清晰,分点列出。 然后,根据引用中的信息,我需要确保每个失效场景都有对应的引用标注。例如,当提到OR条件失效时,引用[2]和引用[3]。对于范围查询后的索引失效,引用[3]指出优化器可能部分使用索引,但后续条件可能失效。LIKE的情况引用[4]。 可能还需要补充其他常见场景,比如对索引列使用函数或表达式,这会导致索引失效,但用户提供的引用中没有提到这点。不过用户的问题可能希望基于提供的引用,所以是否需要包括?根据引用内容,用户提供的引用里没有提到函数导致失效的情况,所以可能不在这里讨论。需要严格按照引用内容来组织答案。 检查是否有遗漏的引用内容。引用[2]还提到OR两边为范围查询时失效。引用[3]提到范围查询后索引可能部分使用,但其他条件可能失效。引用[4]主要讲LIKE的通配符开头问题。引用[1]是结语,没有具体场景。 总结起来,用户提供的引用中的场景包括: 1. OR条件导致失效(引用2) 2. 范围查询后的索引失效(引用3) 3. LIKE以%开头导致失效(引用4) 此外,可能还有其他场景如不遵循最左前缀原则、数据类型隐式转换等,但根据用户提供的引用,可能需要集中在提到的几点。或者用户可能希望更全面的总结,但根据提供的引用,需要基于引用内容来回答。 不过,用户的问题是想了解常见的场景及原因,而提供的引用可能没有涵盖所有情况。但根据指令,回答中引用的段落末尾需要添加引用标识,所以必须确保每个点都有对应的引用来源。因此,我需要严格按照提供的四个引用中的信息来组织答案,可能无法涵盖其他常见场景如函数使用、数据类型转换等,因为引用中没有提到这些。 现在,开始组织回答结构: 第一部分:引言,说明索引失效的重要性,引用[1]的结语部分。 然后分点列出场景: 1. 使用OR条件导致索引失效(引用2) 2. 范围查询后的索引失效(引用3) 3. LIKE操作符以通配符开头(引用4) 4. 其他可能的场景,如果引用中有的话? 检查引用内容: 引用2提到OR条件,其中字段无索引或范围查询导致失效;引用3补充了范围查询后可能部分使用索引;引用4是LIKE的情况。引用1只是结语,没有具体场景。可能还有其他场景如联合索引不遵循最左前缀,但用户提供的引用中没有提到,所以可能不在回答范围内。 因此,主要分三个场景: 1. OR条件导致索引失效 2. 范围查询后的索引部分失效 3. LIKE操作符以通配符开头 每个场景需要详细说明原因,并附上示例和对应的引用。例如: 对于OR条件,当其中一个字段没有索引,整个查询无法使用索引,必须全表扫描,如select * from table where a=1 or b=2,如果b无索引,则索引失效(引用2)。此外,如果OR两边是范围查询,也会失效(引用2)。 范围查询后的情况,例如where a>10 and b=5,如果a和b是联合索引,a的范围查询导致b无法使用索引(引用3)。 LIKE的情况,如where name like '%abc',无法使用索引(引用4)。 确保每个点都有对应的引用标识。然后,在最后生成相关问题,如: 相关问题可能包括如何避免索引失效、如何优化查询语句、索引设计的最佳实践等。 现在,把这些整理成结构清晰的回答,使用中文,分点说明,并正确标注引用。</think>### MySQL索引失效常见场景及原因总结 MySQL索引失效会严重影响查询性能,了解常见场景可帮助优化数据库设计和查询语句[^1]。以下是主要场景及分析: --- #### 1. **使用`OR`条件导致索引失效** - **原因**: - 如果`OR`连接的字段中**至少有一个字段未建立索引**,则整个查询会退化为全表扫描。 - 即使所有字段都有索引,若`OR`两侧为范围查询(如`>`、`<`),索引也可能失效[^2]。 - **示例**: ```sql SELECT * FROM users WHERE age = 25 OR address = 'Beijing'; ``` 若`address`字段无索引,即使`age`有索引,整体查询仍无法使用索引。 --- #### 2. **范围查询后的索引部分失效** - **原因**: - 在联合索引中,如果对某一列进行范围查询(如`BETWEEN`、`>`),其后的列无法继续使用索引。 - MySQL优化器可能仅使用索引的部分条件,后续过滤需在内存中完成[^3]。 - **示例**: ```sql SELECT * FROM orders WHERE create_time > '2023-01-01' AND status = 'paid'; ``` 若索引为`(create_time, status)`,范围查询`create_time > '2023-01-01'`会导致`status`无法利用索引。 --- #### 3. **`LIKE`操作符以通配符开头** - **原因**: - `LIKE`以`%`开头时(如`%abc`),违反**最左前缀匹配原则**,导致索引失效。 - 若通配符仅出现在末尾(如`abc%`),索引仍可能被使用[^4]。 - **示例**: ```sql SELECT * FROM products WHERE name LIKE '%apple%'; -- 索引失效 SELECT * FROM products WHERE name LIKE 'apple%'; -- 可能使用索引 ``` --- #### 4. **其他常见场景** - **数据类型隐式转换**: 若查询条件与索引字段类型不一致(如字符串字段使用数字值),会导致索引失效。 ```sql SELECT * FROM users WHERE phone = 13800138000; -- phone为VARCHAR类型 ``` - **对索引列使用函数或表达式**: 对索引列进行运算或函数调用(如`WHERE YEAR(create_time) = 2023`)会破坏索引结构。 --- ### 优化建议 1. 避免在`WHERE`子句中使用`OR`,改用`UNION`拆分查询。 2. 合理设计联合索引的顺序,将等值查询列放在范围查询列之前。 3. 对高频查询字段建立覆盖索引,减少回表操作。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值