联合索引属于辅助索引。

假如有下图的数据,其中a列是主键:

MySQL联合索引图解 mysql联合索引原理_子节点

如果要创建一个联合索引(b,c,d),那么索引结构类似下图 :

MySQL联合索引图解 mysql联合索引原理_mysql_02

 注意,上图中,叶子节点也存了全部数据,这个结构图示以b,c,d为联合索引建立的,所谓联合索引就是将b,c,d的值连起来以后做排序。需要注意的是,上图中的结构并不是真正的mysql中的结构图,而是类似,在上边的描述中,也用了加粗标红的类似两个字来标注。这里说类似,是因为真正的辅助索引叶子节点不会存全部数据,如果存全部数据,首先占用空间很大,而且数据更新时,辅助索引树也需要更新。真正的辅助索引结构如下图:

MySQL联合索引图解 mysql联合索引原理_联合索引_03

 叶子节点中,没有存储全部数据,而是存储了b,c,d的值和主键的值。

注意:文中提到的节点,是页

联合索引最左匹配:

上边例子中的联合索引是b,c,d,符合最左匹配的会走索引,比如:

select * from t where b=1 and c=1;

那么一下sql会走索引吗?

select * from t where b >1;

答案是不会走索引

MySQL联合索引图解 mysql联合索引原理_辅助索引_04

那么,将条件再次缩小后的sql:

select * from t where b >6;

答案是会走索引

MySQL联合索引图解 mysql联合索引原理_联合索引_05

这里涉及到成本分析:走索引(再回表)和全表扫描。b>1时,虽然有索引可以利用,但需要回表7次,这个成本大于全表扫描。

如果将sql改为以下:

select b,c,d from t where b > 1;

那么就会走索引,这里利用到了索引覆盖。

再次修改sql如下:

select b from t;

也是会走索引的,也是涉及到成本分析:因为辅助索引树的叶子节点数小于主键索引的叶子节点,因为一个节点都是16kb,但是辅助索引的叶子节点只存部分数据。

select b from t where b=1 and c=1;
select b from t where c=1 and b=1;

以上两条语句都会走索引,b和c的顺序不一样,但mysql会优化。