【mysql】之聊聊sql索引使用的规则

看这篇文章建议先看 Explain分析SQL性能

建表SQL

-- 建表
CREATE TABLE `sys_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `v_name` varchar(20) DEFAULT '' COMMENT '姓名',
  `age` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '年龄',
  `pos` varchar(20) NOT NULL DEFAULT '' COMMENT '职位',
  `add_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '入职时间',
  PRIMARY KEY (`id`),
  KEY `idx_name_age_pos` (`v_name`,`age`,`pos`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COMMENT='员工记录表';

-- 建索引
ALTER TABLE sys_user ADD INDEX idx_name_age_pos(`v_name`, age, pos);

1、全值匹配,最优

image

第一个key_len=63,计算规则,v_name varchar(20),20*3+2(动态列类型)+1(允许为NULL)=63

第二个key_len=67,计算规则 v_name+age 长度,63+4(int,不允许为NULL)=67

第三个key_len=129,计算规则,v_name+age+pos,63+4+(20*3+2)=129

2、最佳左前缀(如果建立了联合索引,指的是从索引的最左前列开始并且不跳过索引中的列

image

我们建表索引是idx_name_age_pos,sql1和sql2都没有使用到索引,而sql3没有遵循左匹配也使用到索引,是因为使用了覆盖索引,

覆盖索引:当使用覆盖索引的方式,select id,v_name,age from sys_user where age=10(where后面没有其他没有索引的字段条件),即使不是以v_name开头,也会使用联合索引,总结来说就是

select 后的字段有索引,where字段也有索引,则无关执行顺序,不需要最左边前缀法则

 

3、不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描

image

image

4、索引不能使用索引中范围条件右边的列

image

我们发现sql4和sql2使用的索引是一致的,sql4的pos索引没有用到,说明了范围右边的索引列示法使用到

5、尽量使用覆盖索引,提高查询效率,避免使用select *

6、mysql使用 !=,<>的时候无法使用索引会导致全表扫描

image

7、mysql的is null可以使用索引,is not null 无法使用索引

image

8、like以通配符开头('%abc...')mysql索引失效会变成全表扫描的操作

image

解决like ‘%%’无法使用索引的问题

image

9、字符串不加单引号,导致索引失效

image

10、使用or导致索引字段失效

image

总结:

假设有索引index a_b_c(`a`,`b`,`c`)

where语句

索引是否被使用

where a = 3 a
where a = 3 and b = 5 a,b
where a = 3 and b = 5 and c = 4 a,b,c
where b = 3 或者 where b = 3 and c = 4  或者 where c = 4 没有使用索引
where a = 3 and c = 5 a,因为b中断,所以c索引无法使用
where a = 3 and b > 4 and c = 5 a,b,因为c在范围索引之后,所以无法使用
where a = 3 and b like 'kk%' and c = 4 a,b,c
where a = 3 and b like '%kk' and c = 4 a
where a = 3 and b like '%kk%' and c = 4 a
where a = 3 and b like 'k%kk%' and c = 4 a,b,c

1、对于单键索引,尽量选择针对当前query过滤性更好的索引

2、在选择组合索引的时候,当前Query中过滤性最好的字段在索引字段顺序中,位置越靠前越好。(避免索引过滤性好的索引失效)

3、在选择组合索引的时候,尽量选择可以能够包含当前query中的where字句中更多字段的索引

4、尽可能通过分析统计信息和调整query的写法来达到选择合适索引的目的

原文地址:https://www.cnblogs.com/gyjx2016/p/12462536.html