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');

创建联合索引

ALTER TABLE tmp_table add INDEX name_age_msg(name,age,msg);

表内容

idnameagemsg
1Andy18a
2jerry20j
3kelly25k

type说明:

index:虽然all和index都是扫描全表,但index从索引中读取的,all是从硬盘中读取的。
ref:非唯一性索引扫描,返回匹配某个单独值的所有行,
本质上也是一种索引访问,它返回所有匹配某个单独值的行,然而它可能会找到多个符合条件的行,所以属于查找和扫描的混合体。

测试联合索引生效情况

语句typekey
explain select * from t_user where name = ‘andy’\G;refname_age_msg
explain select * from t_user where age = 20\G;indexname_age_msg
explain select * from t_user where msg = ‘a’\G;indexname_age_msg
explain select * from t_user where name=‘andy’ and age=15\G;refname_age_msg
explain select * from t_user where name=‘andy’ and age=15 and msg=‘a’\G;refname_age_msg
explain select * from t_user where name=‘andy’ and msg=‘a’\G;refname_age_msg
explain select * from t_user where age=15 and msg=‘a’\G;indexname_age_msg
explain select * from t_user where age=15 and msg=‘a’ and name=‘andy’\G;refname_age_msg
explain select * from t_user where age=15 or msg=‘a’ or name=‘andy’\G;indexname_age_msg
explain select * from t_user where age=15 or msg=‘a’\G;indexname_age_msg
explain select * from t_user where name=‘andy’ or age=15\G;indexname_age_msg

接下来创建新的一列,并且此列没有索引。

ALTER TABLE t_user ADD column location VARCHAR(255);

现在表中的内容如下:

idnameagemsglocation
1andy15atext
2jerry20jtext
3kelly25ktext

重复上面的语句,查看联合索引使用情况:

重复上面的语句,查看联合索引使用情况:

序号语句typekey
1explain select * from t_user where name = ‘andy’\G;refname_age_msg
2explain select * from t_user where age = 20\G;ALLNULL
3explain select * from t_user where msg = ‘a’\G;ALLNULL
4explain select * from t_user where name=‘andy’ and age=15\G;refname_age_msg
5explain select * from t_user where name=‘andy’ and age=15 and msg=‘a’\G;refname_age_msg
6explain select * from t_user where name=‘andy’ and msg=‘a’\G;refname_age_msg
7explain select * from t_user where age=15 and msg=‘a’\G;ALLNULL
8explain select * from t_user where age=15 and msg=‘a’ and name=‘andy’\G;refname_age_msg
9explain select * from t_user where age=15 or msg=‘a’ or name=‘andy’\G;ALLNULL
10explain select * from t_user where age=15 or msg=‘a’\G;ALLNULL
11explain select * from t_user where name=‘andy’ or age=15\G;ALLNULL
12explain select * from t_user where name=‘andy’ or location=‘text’\G;ALLNULL
13explain select * from t_user where name=‘andy’ and msg=‘a’ and location = ‘text’\G;refname_age_msg
14explain select * from t_user where name=‘andy’ and msg=‘a’ or location = ‘text’\G;ALLNULL
15explain select * from t_user where name=NULL\GNULLNULL
16explain select * from t_user where name=’’\Grefname_age_msg
17explain select * from t_user where name is null\Grefname_age_msg
18explain select * from t_user where name is null and msg is null\Grefname_age_msg

结论和解释

如上,联合索引会创建(name),(name,age),(name,age,msg)这三个索引。

1,联合索引遵循最左匹配原则,在where…and语句中必须包含name这个“最左字段”,不然的话联合索引不生效。

但是where…and语句中的联合索引这三个字段的顺序可以不一致,只要包含最左的字段就可以使索引生效,因为mysql的sql优化器会优化这些代码。

2,联合索引对or关系不起作用,必须要使用and作为条件

3,使用and作为条件查询,即使存在无索引的条件字段,只要存在有索引的列,explain的结果也会使用到索引,
但是如果使用or作为条件查询,那么只要其中一个字段没有索引,就不会使用索引,而是全表扫描。

col=nullcol 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查询优化器估计使用全表扫描要比使用索引快,则不使用索引。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值