前置知识:

  1. MySQL索引原理


联合索引建立好后,编写SQL的时候,怎么样才会使用上索引呢?有一些匹配的规则。

等值匹配


在 WHERE 子句中,条件的字段和联合索引的字段是一样的,而且条件都是基于等号的等值匹配,这时候就会使用联合索引进行查询。就算 WHERE 子句里面的字段的顺序和索引的字段顺序不一致也没问题,MySQL 会进行优化,将顺序调整成一样的。

最左列匹配


在 WHERE 子句中,不强制条件的字段和索引的字段完全一致才会使用索引查询。从最左侧开始,能匹配多少个字段就可以使用多少个字段进行索引的查询。

例如索引 KEY(age,height,weight)。 使用 WHERE 子句 “WHERE age = 16 “ 这时候就可以走索引,使用 age 字段去匹配数据的。如果条件是”WHERE age=16 AND height = 160 “也会使用 age 和 height 字段去索引数里面匹配。如果条件是”WHERE age=16 AND weight=50” ,那么 age 字段会根据索引查询出来数据页,weight 字段的条件则需要遍历筛选出来的数据才可以找到对应的数据。如果直接是 “WHERE weight=50” ,那么就不会走索引,直接遍历所有数据,不能直接跳过前面2个字段。

最左前缀匹配原则


在 WHERE 子句中,使用 like 查询的时候,如果前缀是确认的,也可以使用索引进行查询的。例如上面的例子,”WHERE age like ‘2%’ “ ,也是可以使用索引查询的。因为索引就是先使用 age 字段从小到大排序,也就可以使用 age 字段来进行二分查找,找到2开头的数据。 如果是 “WHERE age like ‘%2’ “则不行,因为不知道一开始的最左侧的数据是什么。

范围查找规则


WHERE 子句里面如果有范围查询,那只有对联合索引里面最左侧的列进行范围查询才会使用到索引。例如上面的例子,”WHERE age >10 AND age < 20” , 那么就会根据 age 字段在索引里二分查找到 age = 11的数据所在的数据页,然后找到 age = 19 数据行。索引里面的同一个层级的数据页和索引页都是使用双向链表连接起来的。所以截取这两个数据页之间的数据页就可以找到匹配的数据了。 但是”WHERE weight >50” 就无法使用索引查找了,因为 weight >50 的数据,可能在索引树的任何一页,所以需要遍历。

等值匹配+范围匹配规则


WHERE 子句里面如果等值匹配和范围查询。那么也会按照先匹配第1个索引字段的规则。例如”WHERE age = 16 AND height> 160 AND weight>50 “。这时候会先在索引树上定位到 age = 16的数据范围。这些数据还是有序的,而且这些数据里面,也是按照 height 字段从小到大排序的。然后在找到 height > 160的所有数据。这时候,最后一个条件 weight >50 是不能使用索引的,就是 weight 也是索引字段。 因为height > 160 条件筛选后,这些数据就不是根据 weight 字段进行排序了,而是无序的。所以无法使用索引。例如会有一些数据是”height=160 weight=52 , height =166 weight = 51 “。

总体来说,要清楚知道,联合索引是首先按照第1个字段排序,然后按照第2个字段排序。基于这个原则上去匹配数据。必须要先匹配第1个索引字段。不然就不会使用上索引。范围查找后,后面的数据是无序的,所以后面的条件也不会用上索引。