二、数据库索引

65 阅读6分钟

数据库索引

数据结构-树

树只有一个根节点,从根节点延伸出很多其他节点

普通的树结构,每个节点可以有多个子节点

image.png

二叉树

二叉树有树的所有特点,但是有一个不同的地方是,二叉树的每个节点只有两个子节点

image.png

二叉查找树

二叉查找树有二叉树的所有特点,但是二叉查找树的左子节点比父节点小,右子节点比父节点大

image.png

平衡二叉树

平衡二叉树有二叉树的所有特点,并且平衡二叉树的左右子树的高度差不会超过1

image.png

不会出现以下的情况:

image.png

上面根节点的左右子树的高度差已经超过1了,不满足平衡二叉树

B树

B树是多叉平衡查找树。其节点不会只有两个子节点,但是其同一层的节点,从左到右是从小到大排好序的

image.png

B+树

B+树是B树演变而来的,具有B树的基本特征。

B+树与B树不同的是,数据都在叶子节点上,并且叶子节点是用单向链表连接的。B+树结构运用在数据库中用于存储索引信息,叶子节点改用双向链表连接

image.png

数据库索引使用B+树结构而不是B树的原因如下:

  • B+树叶子节点使用双向链表连接,方便范围查询和模糊查询
  • B+树中只有叶子节点存储数据,其他节点存储索引信息,这样一次IO可以读取更多的索引数据,查询效率更高

InnoDB存储引擎支持的索引

B+树结构的索引

聚集索引

聚集索引是由主键作为索引列构建的,如果表中没有指定主键,数据库默认会创建rowid列,作为表的主键列,聚集索引也是通过rowid列构建。rowid是全局递增的,所有的表都共享。

聚集索引的B+树叶子节点上存储了表中行记录的所有信息,示意图如下:

image.png

非叶子节点上存储的是主键的值以及其他节点地址信息

辅助索引

辅助索引是由非主键列指定为索引列而创建的。

其B+树的叶子节点上存储的是索引列的值、主键的值以及其他节点的地址。非叶子节点上存储的是索引列的值和其他节点的地址。

辅助索引的叶子节点中没有包含表中行记录的所有数据,而是通过主键值去聚集索引的B+树中查所有数据,这个操作叫回表。回表操作次数太多会影响查询效率,此时可能还不如全表扫描(mysql的查询优化器会进行sql优化)。

联合索引

联合索引是通过将多个列组合作为一个索引构建的。

其B+树的叶子节点上存储的是联合索引的多个列值、主键的值以及其他节点的地址。非叶子节点上存储的是索引列的值和其他节点的地址。

联合索引的B+树结构中,索引列的值排序是遵循最左前缀原则的。假设联合索引是(A,B,C),那么在B+树结构中,优先保证A列的值从左到右是从小到大排好序的。如果A列中有同样的值,那么再根据B列的值从左到右,从小到大排序。如果B列出现同样的值,再根据C列的值来排序。

联合索引可以减少回表的次数,只要需要的列是联合索引中的列就不需要回表了,在联合索引的B+树中就可以找到值。

联合索引的其他列其实可以为了减少回表操作,提高效率来作为联合索引的一部分。

覆盖索引

覆盖索引不是一种新类型的索引,而是索引的一种特点。是指在辅助索引的B+树上就可以得到需要的列的值,不需要进行回表操作,这种就是覆盖索引。

联合索引很容易是覆盖索引。

哈希索引

B+树索引的查询效率的影响因素就是树的高度。InnoDB的B+树的高度一般在3到4层,所以要经过大概3到4次IO才能查出结果。

mysql对于一些热点数据,为了提高查询效率,会生成自适应哈希索引。这样在查询热点数据的时候,1次IO就可以查询出来,提高效率。

mysql是在5.6版本引入了哈希索引,在5.7版本是默认打开使用哈希索引的。

索引创建策略

创建索引是为了提高数据库的查询效率,所以要遵循一定的策略

  • 索引列的类型越小越好,这样一次IO可以查出更多的索引信息
  • 索引列的枚举值越多越好,这样定位到叶子节点时,包含的主键索引就不会太多
  • 对于内容很长的列,需要创建索引时,可以创建前缀索引。前缀索引是将这个列的值的前面指定长度的数据作为索引值。这种索引构建的B+树的节点上存储的值是列的值的前面一部分,所以按照这种索引查询时,无法使用order by和group by语法
  • 只为查询、排序、分组使用到的列建立索引
  • 创建联合索引时,将枚举值越多的列放在前面

在创建联合索引时,能够满足三星索引要求的,可以称上是好的索引

三星索引要求:

  • 如果索引中包含了要查询的列,那么这个索引可以记上一星。实现是将要查询的列都加到联合索引中
  • 如果查询语句要求的结果顺序与联合索引的顺序一样,可以记上一星。实现是order by语句后面的列加到联合索引中
  • 联合索引可以极大缩小查询的范围。实现是将where语句后的等值条件列作为联合索引的最开头的列。有多个等值条件,就将第一个作为最开头的列,第二个作为第二列,依次类推