联合索引属于辅助索引。
假如有下图的数据,其中a列是主键:
如果要创建一个联合索引(b,c,d),那么索引结构类似下图 :
注意,上图中,叶子节点也存了全部数据,这个结构图示以b,c,d为联合索引建立的,所谓联合索引就是将b,c,d的值连起来以后做排序。需要注意的是,上图中的结构并不是真正的mysql中的结构图,而是类似,在上边的描述中,也用了加粗标红的类似两个字来标注。这里说类似,是因为真正的辅助索引叶子节点不会存全部数据,如果存全部数据,首先占用空间很大,而且数据更新时,辅助索引树也需要更新。真正的辅助索引结构如下图:
叶子节点中,没有存储全部数据,而是存储了b,c,d的值和主键的值。
注意:文中提到的节点,是页
联合索引最左匹配:
上边例子中的联合索引是b,c,d,符合最左匹配的会走索引,比如:
select * from t where b=1 and c=1;
那么一下sql会走索引吗?
select * from t where b >1;
答案是不会走索引
那么,将条件再次缩小后的sql:
select * from t where b >6;
答案是会走索引
这里涉及到成本分析:走索引(再回表)和全表扫描。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会优化。