Bootstrap

关于mysql最左前缀原则

背景知识:

  1. mysql中可以使用explain关键字来查看sql语句的执行计划。
  2. 最左前缀原则主要使用在联合索引中
  3. 数据库版本Mysql5.5.53

1.首先准备如下测试数据表

CREATE TABLE `student` (
  `id` int(11) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  `cid` int(11) DEFAULT NULL,
  `school` char(20) NOT NULL DEFAULT '',
  KEY `name_cid_INX` (`name`,`cid`,`school`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


insert into student values
(1,'weixin',12,'ningbo'),
(2,'weixin',13,'ningbo'),
(3,'weixin',14,'ningbo');

2.我看了很多网上对前缀原则的说明,例如abc联合索引,只有当a或者ab或者abc为条件时才能触发索引,这当然是毋容置疑的,但是我测试了发现ac也是会触发联合索引的,这是为什么呢?

 

我把重点放在了key_len这一项上,key_len是指索引类型的字节长度,那么上面768是怎么计算得到的呢?name列申明的是255,而且字符集是utf8,因此初步计算可以得到值为255*3=765,由于varchar有一个特性就是超过255(应该也包括255)会额外使用两个字节记录长度,因此765还需要加上2,也就是767,又因为name列为null,所以mysql需要1个字节来标识NULL,因此可以计算得出最后结果为768。同理cid列可以计算得到为4+1=5,school列计算得到为20*3=60,那么一个联合索引按照key_len的定义上理解的话,name_cid_INX应该是768+5+60=833,但是为什么ac条件下触发了联合索引,key_len却只是768,网上查了资料发现联合索引可以使用部分,这也是为什么要遵循前缀原则的原因。鉴于联合索引可以使用部分的原因,猜测ac条件之所以触发了联合索引是因为它与单独使用a条件相同,为此对比只使用a条件的情况,具体如下:

发现key_len与ac条件下一致,即验证猜测。接下来我们依次看一下ab和abc条件使用联合索引的情况:

根据以上表述,我们可以得出如下结论:当使用abc会完全使用联合索引的abc三列,使用ab只会使用联合索引中的两列,使用a或者ac只会使用联合索引中的a列,至于其他情况联合索引不会被使用。

3.注意点:细心的读者可能会发现,我们插入的测试数据name都是"weixin"但是查询的时候却没有使用name="weixin"而是使用了name="weixi",原因就是当name="weixin"时命中了表中的大部分数据,mysql查询优化器认为全表扫描比索引索引扫描效率更高而选择了全表扫描,如下:

还有关于mysql的查询优化器还有一点需要注意,sql语句中字段的顺序不需要和联合索引中定义的字段顺序一致,查询优化器会自己调整顺序:

最后欢迎大家关注我的公众号:

;