《高性能mysql》------ 索引(一)

mysql索引

最近一直在看《高性能mysql》,关于索引部分,以前接触过,但是不是特别深入,仅仅了解过主键索引,本片博文用来加深对索引部分的印象,博主学习的《高性能mysql》是2013年5月版,主要是基于 mysql5.5

mysql索引分类

本文主要介绍以下两种索引

  1. B+Tree索引(书中写的是B-Tree,根据译者说明,应该是B+Tree)
  2. 哈希索引

B+Tree索引

既然原书中写的是 B-Tree,我们就简单介绍一下 B-Tree,介绍 B+Tree时也方便一点

B-Tree 是 B树而不是 B减树,中间的 - 是连接符
B-Tree 是一种多叉平衡查找树,对比二叉平衡查找树(又叫 avl树),B-Tree 每个节点的子节点数目可以大于两个,如果B-Tree树中每个节点的子节点数目最大为 m,则为m阶B-Tree,除此以外B-Tree与 avl树没有明显的不同

B+Tree 是在 B-Tree树上的一种拓展,百科上面对B+Tree讲述的比较细致,这里主要有三点需要额外的注意

  1. 除了最后的叶子节点,每个叶子节点都有指向下一个叶子节点的指针,从而所有叶子节点形成了一个有序的链表,连续顺序查找时会非常节省时间
  2. 每个非叶子节点不存储具体的数据(严格来说时指向数据的指针),而仅仅存储键
  3. 当索引的键不止一个时(譬如,使用 作为索引)时,只有在前一个键匹配的情况下才能去查找下一个。譬如,如果 last_name匹配,则可以去匹配 first_name,如果 first_name也已经匹配,则可以去匹配 date。如果不提供 last_name的值,则不能直接去匹配 first_name,也不能直接去匹配 date

B+Tree示意图如下

图片来自百度百科

我们可以模拟一下B+Tree索引的查找过程
譬如,我们需要查找 ,首先我们需要建立这样的索引 key(last_name,first_name,date,time),上图中的 key就变成数据库中这四个项的组合,然后

  1. 根据 last_name=Y 在对应的 B+Tree中查找
  2. 找到对应索引后,再根据 first_name查找
  3. 找到对应索引后,再根据 date=2020.10.26查找(如果这里 date是范围表示,譬如 date<2030.1.1,则time索引不会被查找)
  4. 最后按照 time索引查找

在查找到对应的叶子节点后,直接访问也叶子节点指向的数据行,查找过程结束。

我们回顾一下查找过程,主要的耗时在于索引树的遍历,假设我们使用的是 m 阶B+Tree,树的深度为 log(m)n,每一层查找平局耗时为 m/2,网上很多地方说这里可以用二分查找,但是博主仔细想了一下,第一,除非叶子节点,否则同一个父亲的子节点之间没有关联(只有叶子节点才用“串”起来)。第二,哪怕是叶子节点,他们之间的关联方式为指针连接,也很难通过下标的方式访问子节点

那么一次查找的平均耗时为 m/2*log(m)n,1/2为常数,可以省略,耗时可以写成 log(m^(1/m))n,对m^(1/m)求导可知,当 m=e的时候取最大值,此时耗时为最小值,由于这里m为整数,所以当 m=3时,有最好的效率,复杂度为 O(log(3)n)

如果我们不使用索引,直接查找数据行,复杂度为 O(n)

哈希索引

哈希索引使用哈希表实现,通过对不同的键值进行哈希计算,得到哈希码,通过访问哈希码能快速的访问到数据行

我们假设,使用 fname建立哈希索引,我们执行如下查询

SELECT lname FROM testhash WHERE fname='Peter';

通过哈希索引访问过程如下

  1. 计算 Peter的哈希值
  2. 使用哈希值查询到对应的记录指针
  3. 使用记录指针找到对应的数据行,并判断该行的 fname是否等于 Peter

由于底层使用了哈希表,所以查询速度非常快,不过哈希索引也存在着一定的问题

  1. 哈希索引不支持部分索引列匹配查找。
    使用 B+Tree索引时,如果我们无法对整个查询字段进行索引查找,我们也可以根据前几项索引来优化我们的查找速度,但是哈希索引是建立时就将所有字段组合之后进行哈希,所以只提供部分字段值,我们无法生成对应的哈希值,也就无法使用哈希查找
  2. 哈希索引不支持范围查找。
    由于字段经过哈希函数之后已经无法比较大小,所以范围查找是无法通过哈希索引的
  3. 如果哈希冲突很多,查找和维护的代价也会很高

综上,哈希索引在部分情况下效率极高,特别是当数据行的键重合度比较低,查询多是等值查询时。我们可以在通过做CRC32或者取用MD5的一部分作为我们的键,降低数据行的键重合度来优化我们的哈希索引。

你可能感兴趣的:(《高性能mysql》------ 索引(一))