案例所用的表结构、索引、与数据如下:
索引失效与优化
1、全值匹配我最爱
2、最佳左前缀法则(带头索引不能死,中间索引不能断)
如果索引了多个列,要遵守最佳左前缀法则。指的是查询从索引的最左前列开始 并且 不跳过索引中的列。
正确的示例参考上图。
错误的示例:
带头索引死:
中间索引断(带头索引生效,其他索引失效):
3、不要在索引上做任何操作(计算、函数、自动/手动类型转换),不然会导致索引失效而转向全表扫描
4、mysql存储引擎不能继续使用索引中范围条件(bettween、<、>、in等)右边的列
5、尽量使用覆盖索引(只查询索引的列(索引列和查询列一致)),减少select *
6、索引字段上使用(!= 或者 < >)判断时,会导致索引失效而转向全表扫描
7、索引字段上使用 is null / is not null 判断时,会导致索引失效而转向全表扫描
8、索引字段使用like以通配符开头(‘%字符串’)时,会导致索引失效而转向全表扫描
由结果可知,like以通配符结束相当于范围查找,索引不会失效。与范围条件(bettween、<、>、in等)不同的是:不会导致右边的索引失效。
问题:解决like ‘%字符串%’时,索引失效问题的方法?
使用覆盖索引可以解决。
9、索引字段是字符串,但查询时不加单引号,会导致索引失效而转向全表扫描
10、索引字段使用 or 时,会导致索引失效而转向全表扫描
小总结
##########################################################################################
mysql 索引失效原因
一、单表查询时索引失效
1、mysql查询单表时,查询得到的结果集占数据总量很大比例,mysql会认为全表扫描会优于索引,则不走索引。
例:比如企业人员信息表 (userInfo),字段(user_id、user_name、user_type(vachar)),假设企业里有10w人,一千个管理层user_type为1,9万9千人为普通员工user_type为2,
sql:select * from userInfo where user_type='2' 这时user_type字段索引可能会失效
2、查询时where条件后的字段类型要与表结构中该字段类型一致,
例:select * from userInfo where user_type=2 ,user_type在表结构中时字符类型,查询时没用有单引号包含起来则不走索引。
3、在where条件后对索引字段加了函数转换或者运算逻辑(+、-、*、/、!、<>、%、like'%_'(%放在前面)、or、in (疑问、可能存在成本问题)、exist等)的处理,比如对时间戳字段进行日期格式化函数都会引起索引失效。
二、多表关联查询时索引失效
1、在表结构设计阶段主表与关联表之间的关联字段的数据类型、数据长度、字段的编码格式以及字段的排序规则需要保持一致
三、组合索引
1、当一张表的查询方式比较固定,这时候可以尝试创建聚集索引,查询时应当遵从组合索引的规则,最左原则,查询时使用最频繁的一列放在最左边,
例:index(user_id,user_name,user_type)这是一个组合索引,当查询时如果想走索引则
sql:select * from userInfo where user_id='001' and user_name='小张' and user_type='1';这个时候是走了索引的,但是
select * from userInfo where user_name='小张' and user_type='1';这时user_id没有在where条件内将不走索引;
此例,user_id字段必须出现在where后面,不然索引将不会生效。