1、聚集索引(主键索引)

将数据存储与索引放到了一块,索引结构的叶子节点保存了行数据(所有字段的值)

2、非聚集索引(辅助索引)

将数据与索引分开存储,索引结构的叶子节点指向了数据对应的位置

总结:

在存储引擎为 InnoDB 的表中,主键索引的类型是聚簇索引,辅助索引的类型是都是非聚簇索引。结合上边对聚簇索引、非聚簇索引的定义,我们可以知道,InnoDB 的表中主键索引中的叶子点上存储了行数据(所有字段的值,而辅助索引叶子节点存储了索引列的值和主键值。

2.1、聚集索引和非聚集索引图解:

InnoDB的聚集索引

 InnoDB的非聚集索引

图示根据主键查询的过程:

 

整个查询的过程如下:

查询 id(主键) 为 18 的数据,SELECT id, name, age WHERE id = 18。首先在「根节点:节点一」上,id = 18 落在了 15 <= id < 56 范围之内,这样我们就知道了下级节点「非叶子节点:节点2-1」的地址。根据【步骤2】得到的「非叶子节点:节点2-1」的地址,找到对应的「非叶子节点:节点2-1」。然后,id = 18 又落在了 15 <= id < 20 范围之内,这样我们就知道了再下一级节点「叶子节点:节点3-1」的地址。根据【步骤3】得到的「叶子节点:节点3-1」的地址,找到对应的「叶子节点:节点3-1」。最后,在「叶子节点:节点3-1」这个节点上找到 id = 18 对应的数据 {“id”: 18, “name”: “King”, “age”: 17}

2.2、MyISAM

在存储引擎为 MyISAM 的表中,主键索引和辅助索引的类型都是非聚簇索引。两棵 B+Tree 的结构完全一致,只是存储的内容不同,主键索引 B+Tree 的节点存储了「主键」+「数据记录的地址」,辅助键索引 B+Tree 存储了「索引列的值」+「数据记录的地址」。还有一点不同是主键索引中的 key 必须是唯一的,而辅助索引中的 key 可以重复。

MyISAM-主键索引

MyISAM-辅助索引(非聚簇索引)

3、索引覆盖

索引中已经包含了所有需要读取的列数据的查询方式称为覆盖索引(或索引覆盖)。 简单来说查询时减少回表次数了。

如果非聚簇索引的叶子节点上有我们想要的返回的数据(字段),那就不需要回表了。

例如: name 和 idcard 字段创建了一个联合索引(非聚簇索引), 我们只想返回 主键、name、idcard 这 3 个字段(SELECT id, name, idcard WHERE name = “那XX”), 因为 name、idcard 作为一个联合索引已经在辅助索引上的叶子节点上存有 name、idcard 的具体值,所以就不需要再回表操作了(除非 SELECT 里再增加一个 address 字段,这样就需要回表了)。

4、索引下推 

索引条件下推就是 “过滤的动作 尽量由 下层的存储引擎层 通过 使用索引 来完成,而不需要上推到 Server 层进行处理。

索引下推,严格来说应该叫「索引条件下推」。该功能是 MySQL 数据库 5.6 版本添加的,用于优化数据查询,默认情况处于开启状态。我们可以通过如下命令来开启和关闭「索引条件下推」功能:

开启

SET optimizer_switch = 'index_condition_pushdown=on'

关闭

SET optimizer_switch = 'index_condition_pushdown=off'

下面通过一个例子来说下什么是「索引条件下推」,首先我们假设有这么一张表:

表名:t_user字段:id,name,mobile辅助索引:name + mobile(索引名:name_mobile_normal)

下面,让我们来分别看下关闭和开启「索引条件下推」这两种情况,下边这个查询语句的执行计划有怎样的不同

EXPLAIN SELECT * FROM t_user WHERE name = 'A' AND mobile LIKE '%138'

关闭「索引条件下推」

开启「索引条件下推」

 从上边,我们可以看到,关闭「索引条件下推」时候 Extra 是 Using where;开启「索引条件下推」时候 Extra 是 Using index condition。

索引下推案例:

select * from t_user where name like 'L%' and age = 17;

这条语句从最左匹配原则上来说是不符合的,原因在于只有name用的索引,但是age并没有用到。

不用索引下推的执行过程:

第一步:利用索引找出name带'L'的数据行:LiLei、Lili、Lisa、Lucy 这四条索引数据

第二步:再根据这四条索引数据中的 id 值,逐一进行回表扫描,从聚簇索引中找到相应的行数据,将找到的行数据返回给 server 层。

第三步:在server层判断age = 17,进行筛选,最终只留下 Lucy 用户的数据信息。

使用索引下推的执行过程:

第一步:利用索引找出name带'L'的数据行:LiLei、Lili、Lisa、Lucy 这四条索引数据

第二步:根据 age = 17 这个条件,对四条索引数据进行判断筛选,最终只留下 Lucy 用户的数据信息。

(注意:这一步不是直接进行回表操作,而是根据 age = 17 这个条件,对四条索引数据进行判断筛选)

第三步:将符合条件的索引对应的 id 进行回表扫描,最终将找到的行数据返回给 server 层。

比较二者的第二步我们发现,索引下推的方式极大的减少了回表次数。

索引下推需要注意的情况:

下推的前提是索引中有 age 列信息,如果是其它条件,如 gender = 0,这个即使下推下来也没用

相关阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: