面试的时候总会遇到面试官问MySql索引的问题,而且一般都会问到关于索引失效的情况,哪种查询会使用索引,哪种查询不会走索引。本人之前面试也会遇到这样的问题,但是总感觉不够全面,今天我就把关于MySql的相关索引使用场景总结一下。
索引: 索引是对表中的一列或者多列的数据进行排序的物理结构。
联合索引: 两个或更多个列上的索引被称作联合索引,联合索引又叫复合索引。
5.7.29 MySQL Community Server (GPL)
CREATE TABLE t_user (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255),
age INT,
msg VARCHAR(255)
);
INSERT INTO t_user (name,age,msg) values ('Andy',18,'a'),('jerry',20,'j'),('kelly',25,'k');
id | name | age | msg |
---|---|---|---|
1 | Andy | 18 | a |
2 | jerry | 20 | j |
3 | kelly | 25 | k |
ALTER TABLE tmp_table add INDEX name_age_msg(name,age,msg);
语句 | type | key |
---|---|---|
explain select * from t_user where name = ‘andy’\G; | ref | name_age_msg |
explain select * from t_user where age = 20\G; | index | name_age_msg |
explain select * from t_user where msg = ‘a’\G; | index | name_age_msg |
explain select * from t_user where name=‘andy’ and age=15\G; | ref | name_age_msg |
explain select * from t_user where name=‘andy’ and age=15 and msg=‘a’\G; | ref | name_age_msg |
explain select * from t_user where name=‘andy’ and msg=‘a’\G; | ref | name_age_msg |
explain select * from t_user where age=15 and msg=‘a’\G; | index | name_age_msg |
explain select * from t_user where age=15 and msg=‘a’ and name=‘andy’\G; | ref | name_age_msg |
explain select * from t_user where age=15 or msg=‘a’ or name=‘andy’\G; | index | name_age_msg |
explain select * from t_user where age=15 or msg=‘a’\G; | index | name_age_msg |
explain select * from t_user where name=‘andy’ or age=15\G; | index | name_age_msg |
这些是联合索引生效的情况。
接下来创建新的一列,并且此列没有索引。
ALTER TABLE t_user ADD column location VARCHAR(255);
更新location的数据,不让其为NULL(避免值为NULL的列影响索引的使用,实际上值是否为NULL并不会对索引是否生效造成影响。)
UPDATE t_user set location = 'text';
现在表中的内容如下:
id | name | age | msg | location |
---|---|---|---|---|
1 | andy | 15 | a | text |
2 | jerry | 20 | j | text |
3 | kelly | 25 | k | text |
重复上面的语句,查看联合索引使用情况:
重复上面的语句,查看联合索引使用情况:
序号 | 语句 | type | key |
---|---|---|---|
1 | explain select * from t_user where name = ‘andy’\G; | ref | name_age_msg |
2 | explain select * from t_user where age = 20\G; | ALL | NULL |
3 | explain select * from t_user where msg = ‘a’\G; | ALL | NULL |
4 | explain select * from t_user where name=‘andy’ and age=15\G; | ref | name_age_msg |
5 | explain select * from t_user where name=‘andy’ and age=15 and msg=‘a’\G; | ref | name_age_msg |
6 | explain select * from t_user where name=‘andy’ and msg=‘a’\G; | ref | name_age_msg |
7 | explain select * from t_user where age=15 and msg=‘a’\G; | ALL | NULL |
8 | explain select * from t_user where age=15 and msg=‘a’ and name=‘andy’\G; | ref | name_age_msg |
9 | explain select * from t_user where age=15 or msg=‘a’ or name=‘andy’\G; | ALL | NULL |
10 | explain select * from t_user where age=15 or msg=‘a’\G; | ALL | NULL |
11 | explain select * from t_user where name=‘andy’ or age=15\G; | ALL | NULL |
12 | explain select * from t_user where name=‘andy’ or location=‘text’\G; | ALL | NULL |
13 | explain select * from t_user where name=‘andy’ and msg=‘a’ and location = ‘text’\G; | ref | name_age_msg |
14 | explain select * from t_user where name=‘andy’ and msg=‘a’ or location = ‘text’\G; | ALL | NULL |
15 | explain select * from t_user where name=NULL\G | NULL | NULL |
16 | explain select * from t_user where name=’’\G | ref | name_age_msg |
17 | explain select * from t_user where name is null\G | ref | name_age_msg |
18 | explain select * from t_user where name is null and msg is null\G | ref | name_age_msg |
如上例子,联合索引会创建(name),(name,age),(name,age,msg)这三个索引。
联合索引遵循最左匹配原则,在where…and语句中必须包含name
这个“最左字段”,不然的话联合索引不生效。
但是where…and语句中的联合索引这三个字段的顺序可以不一致,只要包含最左的字段就可以使索引生效,因为mysql的sql优化器会优化这些代码。
联合索引对or关系不起作用,必须要使用and作为条件。
使用and作为条件查询,即使存在无索引的条件字段,只要存在有索引的列,explain的结果也会使用到索引,但是如果使用or作为条件查询,那么只要其中一个字段没有索引,就不会使用索引,而是全表扫描。
col=null
和col is null
查询的区别1,col=null
无法使用索引,并且也查询不出数据。
2,是否使用索引只与查询条件是否使用col=null
有关,而与列的数据是否存在null值的行无关。
3,空字符串与null并不相等,且不可替换,针对这两个值的查询语句和结果都不一样。
如果name列存在一行值为空字符串,则需要使用
name=''
条件来查询。并且可以使用索引。
1,询条件中包含 !=
或 <>
。
2,条件中有 or
,但是有其中一个 or
没有建立 index
。
3,like
查询以 %
开头
4,如果列类型是字符串,那要在条件中将数据用引号引用起来,即使查询的数据是一个字符串整型。
5,如果查询条件里面包含 col=null
则此列的索引不生效。并且也查询不出数据,必须使用 col is null
语句才能使索引生效。
6,如果mysql查询优化器估计使用全表扫描要比使用索引快,则不使用索引。
本篇文章简单介绍了MySql的联合索引以及索引失效情况,由于纯手打,难免会有纰漏,如果发现错误的地方,请第一时间告诉我,这将是我进步的一个很重要的环节。