Mysql联合索引是怎么存储的

  |   0 评论   |   0 浏览

联合索引

联合索引是将多列作为索引字段建立B+树。但是实际上MySQL只会为一个联合索引建立一个B+树。如使用C2和C3作为联合索引,规则如下:

  • 先把各个记录和页按照c2列进行排序。
  • 在记录的c2列相同的情况下,采用c3列进行排序

1710954877027020800.png

每条目录项记录都由c2、c3、页号这三个部分组成,各条记录先按照c2列的值进行排序,如果记录的c2列相同,则按照c3列的值进行排序。

最左前缀原则

在平时开发中,最常见的是单列索引(比如主键primary id),但是在需要多条件查询的时候,也会创建联合索引。单列索引也可以看成特殊的联合索引。比如在user表中,给name和phone建立一个联合索引。

ALTER TABLE user_innodb add INDEX comidx_name_phone(name,phone); -- 创建联合索引

下图是B+树的索引结构,是一个单值索引:

在这里插入图片描述

可以看出,所有非叶子节点的构成都是由两部分组成,索引值+指针,而单值索引说的就是在索引值这里只有一个值(比如id),而联合索引在索引值可能会有多个值(比如name和phone)

在这里插入图片描述

与单值索引的不同

  • 联合索引在B+树中是复合的数据结构
  • 由于B+树本身是有序的,所以联合索引是从左到右的顺序来建立搜索树的(name在左边,phone在右边)。从上图可以看出,name是有序的,phone是无序的。当name相等时,phone才是有序的。
  • 当存储引擎是innoDB时,叶子节点存储的是数据/主键

Q1:联合索引如何查找数据?

比如,使用where name = ‘zhangsan’ and phone='1320xx’去查询数据的时候

  • B+树会优先比较name来确定下一步应该搜索的方向,往左还是往右
    如果name相同的时候就比较phone
  • 但是如果查询条件没有name,就不知道第一步应该查询哪个节点,因为建立搜索树的时候name是第一个比较因子,所以用不到索引。

Q2:联合索引与单值索引的关系?
假设项目里有两个查询很慢:

SELECT * FROM user_innodb WHERE name= ?;
SELECT * FROM user_innodb WHERE name= ? AND phone=?;

按照我们的想法,一个查询创建一个索引,所以针对这两条SQL创建两个索引,这种做法觉得正确吗?

CREATE INDEX idx_name on user_innodb(name);
CREATE INDEX idx_name_phoneonuser_innodb(name,phone);

当我们创建一个联索引的时候,用左边的字段name去查询的时候,也能用到索引,所以单独为name创建一个索引完全没必要,相当于建立了两个联合索引(name),(name,phone)

如果创建三个字段的索引index(a,b,c)相当于创建三个索引:index(a),index(a,b),index(a,b,c)。用where b=?和where b=? and c=? 和where a = ? and c = ?是不能使用到索引。以为不能不用第一个字段,也不能中断。

因为联合索引中包含了多个字段,所以不能像单值索引那样直接使用,需要遵守规则?
就是最左前缀原则:带头大哥不能死,中间兄弟不能断

1.建立索引时,一定要把常用的列放在最左边。比如下面三个语句,能用到联合索引吗?
使用两个字段,可以用到联合索引(注:两个字段的顺序颠倒并不影响,因为全值匹配时mysql会优化字段顺序)

EXPLAIN SELECT * FROM user_innodb WHERE name= '张三' AND phone='12345678910'

2.使用左边的name字段,可以用到联合索引:

EXPLAIN SELECT * FROM user_innodb WHERE name= '张三'

3.使用右边的phone字段,无法使用索引,全表扫描:

EXPLAIN SELECT * FROM user_innodb WHERE phone= '12345678910'

不要在索引上做任何操作,因为可能会导致索引失效,转而全表扫描

参考原文链接:https://blog.csdn.net/qq_38487209/article/details/125111125


标题:Mysql联合索引是怎么存储的
作者:michael
地址:https://blog.junxworks.cn/articles/2023/10/08/1696758485950.html