Почему Mysql использует дерево B+ для реализации индекса

Почему Mysql использует дерево B+ для реализации индекса

В этой статье в основном обсуждается, почему Mysql использует деревья B+ для реализации индексов.Цель, обсуждаемая здесь, - механизм InnoDBхранения Mysql.Представьте, если вы разработчик Mysql, как бы вы выбрали подходящую структуру данных?

Начиная с реальной сцены

Любая структура данных создается для решения конкретных задач, поэтому, если пользователь использует Mysql, какие требования?Мы можем легко придумать самые простые требования:

  1. Сопоставить запрос по идентификатору или другим значениям столбца
  2. Запрос диапазона по id

Пользователи определенно надеются, что производительность запроса будет максимально высокой.Для таблицы, если данные можно запрашивать напрямую через индекс без необходимости выполнять полное сканирование таблицы, это было бы здорово.

Выберите правильную структуру данных

В это время разработчики Mysql начнут выбирать подходящую структуру данных для решения проблемы производительности запросов пользователя.Можно придумать альтернативы, включающие Hashэти B Treeтри B+ Treeструктуры данных.

Если Hash используется в качестве структуры данных индекса

Хэш может обеспечить сложность запроса O (1). Для аналогичного select * from t where id = 3эквивалентного сопоставления производительность довольно высока, что можно сказать, не имеет себе равных. Но для диапазонных запросов хэш немного растянут. Хэш не имеет Метод заключается в использовании сложности O(1) для выполнения запроса диапазона, из-за этого Hash не подходит для реализации базового индекса.

Используйте B-дерево или B+-дерево

Тогда остаются единственные варианты: Дерево B и Дерево B +, Поскольку структуры данных двух в чем-то похожи, при выборе между этими двумя структурами данных лучше всего сравнить их вместе, чтобы более четко знать, какие данные лучше. состав.

Прежде всего, мы должны четко понимать, как B-дерево хранит данные.Вот картинка:

b tree structure.png

我们现在以聚簇索引来举例,图中的数字代表主键值,后面的*代表该位置是存放实际的行数据的.每个节点的左指针指向下一级的节点,并且左边指向的节点的主键值大小比上一级的小,右边指向的节点的主键值比上一级的大.B Tree的一个重要特点是在每一个节点都存储了完整的行数据.

B+ Tree存储数据的方式是这样的:

B+ Tree Structure.png

B+ Tree的重要特点是:

  1. 只有叶子节点才会存放整行数据,而非叶子节点只存储主键值,用于向下搜索

  2. 叶子节点冗余了所有的主键值,并存储行数据,并且每个节点之间用双向链表进行连接

在图中的12这个节点中,后面是指向24这个节点的,在图中被省略了.

在这里,我们再强调一下B Tree和B+ Tree的重要区别:

  1. B Tree的每个节点都存储行数据,而B+ Tree只有叶子节点存放行数据.
  2. B Tree因为每个节点都存储行数据,所以没有必要在非叶子节点再冗余任何数据.B+ Tree因为只有叶子节点存储行数据,所以需要在最后一层冗余所有的主键值,并存储行数据,且节点之间用链表进行连接.

理解了这两者的区别之后,我们来考虑一下针对实际场景,哪个数据结构才是更好的选择.首先,我们考虑一下等值查询,对于B Tree来说,从根节点的主键值开始进行比较,根据左小右大的特点,可以在某个层级定位到整行数据并返回.对于B+ Tree来说,也是从根节点开始进行比较,不过最终必须定位到叶子节点才能获取到需要的数据.所以在等值查询这个场景下,B Tree看起来比B+ Tree来得好.

那么考虑一下范围查询,比如B Tree来说,查询数据跟等值查询的模式差不多,只不过需要扫描到多个层级的节点.举个例子,如果在上图中寻找主键大于等于10且小于等于24的行数据.

  1. 首先从根节点12开始,12是满足条件的,所以获取它的行数据,12后面的同级节点24也符合要求,所以也获取它的行数据.
  2. 从12的左指针找到下一个节点,第一个节点是8,不符合要求,之后向后找到它的同级节点10,符合要求,后面没有其他节点了,结束.
  3. 节点12的右指针(节点24的左指针)没有指向任何数据,所以无需再找到下一个节点,所有可能的节点都查询过了,查询结束.

我们可以从这个过程中看到,范围查询需要从根节点出发,然后可能要找到它的下一级节点,直到找到所有符合的数据.

对于B+ Tree来说,寻找主键大于等于10且小于等于24的行数据的流程是这样的:

  1. 从根节点12向左找到下一级的10这个节点,从10的左指针找到10所在的叶子节点,因为叶子节点是链表结构,那么可以从这个叶子节点的指针一直往后定位到24这个节点,然后返回这中间的所有数据.

实际上数据最终都是存储到磁盘上的,对于Mysql来说,数据是以页为单位来存储数据,通常为4KB,在上面的图中,我们可以理解成每一个大的长方形框是一个页,而每个页里面存放了很多节点,对于B Tree来说,每个页的节点都存放整行数据,对于B+ Tree来说,非叶子页的节点只存放id,也被称为索引页,而叶子节点存放整行数据.对于页的读取,就涉及到IO操作,要知道IO读取数据的速度比从内存读取数据要慢得多,通常读取页的时间在10ms左右.

以范围查询为例,我们从IO的角度来概括一下B Tree和B+ Tree的区别.对于B Tree而言,读取根节点需要一次IO操作,加载出页之后,当前页的数据可能只有部分符合要求,然后根据页的指针再进行IO操作,找到另外的页,整个过程需要更多的IO操作,并且因为每次读取的页并不是所有数据都满足要求,所以这种方式被称为随机IO.那么对于B+ Tree而言,也需要从根节点向下查询,这其中也涉及到随机IO,但定位到需要的叶子节点后,读取页时只需要根据链表来定位到下一个页,每次读取的页大概率都是符合要求的数据,这种方式被称为顺序IO.所以在范围查询中,B Tree需要更多的IO操作,这样就需要耗费更多的时间.如果对随机IO和顺序IO不是很理解,文末有个参考资料可以去看一下.

所以整体上来看,B+ Tree是更好的选择.

参考资料

Supongo que te gusta

Origin juejin.im/post/7235052693386264636
Recomendado
Clasificación