【Mysql】 索引相关知识点

426 阅读4分钟

mysql索引

聚簇索引

也叫聚集索引,第一索引。

聚簇索引一般是主键索引,如果没有主键索引,那么就使用唯一索引,如果没有唯一索引,那么就使用唯一的row_id,这个是一个隐藏值,如果没有前面说的那些索引,每一行会自动生成row_id。

聚集索引的结构

聚集索引内部是使用B+树结构来进行构建的, 而B+树的结构为内部节点与叶子节点:

Mysql中B+树的特性

  • 我们使用的mysql存储引擎是Innodb
  • InnoDB存储引擎最小储存单元是页,一页大小就是16k
  • 每个节点的大小都是一页,这个页可以自定义,默认是16K
  • 内部节点(非叶子节点)不存储数据,只存储指针和聚簇索引的值
  • 叶子节点存储真实的数据行
  • 索引值是有序的

B+树结构类似于下图:

image.png

图里的data就是真实数据。

查询的效率是很高的,每一层根据二分法来寻找指定的索引值。

非聚簇索引的结构

非聚簇索引与聚簇索引类似,但是它叶子节点不存完整数据,而是存聚簇索引值。

非聚簇索引的特点

  1. 非叶子节点存储索引列的值
  2. 叶子节点存储索引列及对应的聚簇索引的值
  3. 二级索引获取除二级索引值外的数据需要走一遍聚集索引

搞懂聚簇索引和非聚簇索引的结构之后,就可以来解释一些相关知识点。

索引进行和等值,范围查询

  1. 等值查询: 去B+树叶子节点找到某一个页,然后遍历这个页,就能找到指定值。

  2. 范围查询: 先根据等值查询找到指定值, 然后往后或往前遍历数据,找到范围值。

联合索引

假设有一个索引(a,b,c):

abc
1510
188
3812
61015
7114
1061
1062

从a开始排序,保证a总体为非递减序列; 当a相同, 保证b为非递减序列; 当b相同,保证c为非递减序列

出几道题来加深理解:

索引(a,b,c)

  1. select * from t where a = 1 and b = 3 and c = 2; 先匹配a,再匹配b,再匹配c。
  2. select * from t where a = 1 and b > 3 and c = 5; 先匹配到a, 然后在找到b大于3的部分,这个时候c是没有顺序的,因此c会匹配失效
  3. select * from t where a > 5 and b = 5 and c = 5; 先匹配a的部分,然后b是无序的,所以后面部分的索引匹配会失效。
  4. select * from t where b = 5; 会失效,因为b在(a,b,c)中,a不确定的情况下,b是无序的,因此会失效

索引覆盖

比如有索引(a,b), 我查找 select a,b from t where a = 1 and b = 2;

索引覆盖: 当我们使用二级索引时,所要查找的列刚好被包含在二级索引中,我就不用去聚集索引找数据了。

这就叫索引覆盖。

回表

什么是回表,回表是一种操作,当上面的索引覆盖失效了的时候,就会进行回表操作。

比如有索引(a, b), 我执行select a,b,c from t where a = 1 and b = 2 , 这个时候会去二级索引获取查a, b。

但是我二级索引里面并没有c的数据,因此二级索引拿到聚集索引的值,去聚集索引里面走一遍,获取数据。

为什么不建议使用UUID做主键

  1. UUID无序,添加数据很容易动整个B+树,进行分裂合并。
  2. UUID字段长, 占用内存大,导致节点里面存的数据变少,树变高,IO次数增多

为什么长字段要拆成附表

page存的数据越多,索引树越高,导致查询时IO次数多,效率低。


上面写了这么多理论,我们去实战一下:

实战

  1. 像我这样创建一个表book:

image.png

  1. 然后建立一个联合索引:

image.png

  1. 我们去使用explain语句来看我们的select情况:

    那么你先去这个网页去看看explain关键字的参数: explain参数详解-CSDN博客

看了参数详解后,我们使用explain来解释一些select语句.

  1. 先来个全表查询

image.png

可以看到并没有使用索引,type = all 全表查询

  1. 使用主键索引:

image.png

type变为const

  1. 使用非主键索引: image.png

用到了索引.

那如果我使用其中一个的呢???

image.png

可以看到按顺序可以使用到索引。

如果不按顺序:

image.png

可以看到退化为全表查询,索引失效