digital-garden/dev/fundamental/structure/B-tree.md
Struchkov Mark 8b4fb13112
All checks were successful
continuous-integration/drone/push Build is passing
Обновление
2024-11-05 01:01:35 +03:00

81 lines
8.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
aliases:
tags:
- maturity/🌱
date: 2024-01-29
---
[[Сбалансированное дерево|Сбалансированное]] сильно-ветвистое дерево позволяет хранить в узле множество значений, что делает его эффективным для работы с большими объемами данных.
![](../../../meta/files/images/Pasted%20image%2020240205190752.png)
**Основные особенности B-tree**
- Узел содержит множество элементов, что позволяет хранить больше данных в одном месте.
- Каждый узел представляет собой [[../Страница|страничку]] на диске, что снижает издержки на чтение.
- В каждом узле есть ссылки на следующий и предыдущий узлы (характерно для B+tree). Это сильно помогает с поиском по диапазонам.
- В листьях дерева могут храниться сами данные или указатели на данные, то есть ссылаются на таблицу.
- Элементы в узле отсортированы, что делает поиск более эффективным и позволяет создавать деревья с небольшой высотой, тем самым уменьшая количество обращений к диску.
- Значения в узлах могут быть не уникальными.
- Обычно высота дерева не больше 3-4 уровней.
## Параметр t
Параметр `t` определяет количество элементов в узле дерева.
- В каждом узле должно быть не менее `t-1` и не более `2t-1` ключей. Это правило важно для поддержания сбалансированности дерева, так как позволяет равномерно распределять элементы между узлами и поддерживать эффективную высоту дерева, что, в свою очередь, обеспечивает высокую производительность операций поиска.
- Это правило не выполняется для корневого узла.
**Как выбрать `t`**: значение `t` влияет на высоту дерева — ==большее значение уменьшает высоту, что снижает количество обращений к диску.== Обычно `t` выбирается в диапазоне от 50 до 2000 в зависимости от размера блока на диске и объема [[../../../../../knowledge/dev/pc/Оперативная память|оперативной памяти]]. Например, при `t = 1001` и 1 млрд записей требуется всего 3 операции для поиска любого ключа.
## Применение B-tree
**С чем может помочь:**
- **Поиск по равенству**: `a = 5`
- **Поиск по открытому диапазону**: `a > 5` или `a < 3`
- **Поиск по закрытому диапазону**: `3 < a < 8`
- **LIKE** работает с индексами по префиксам (`LIKE 'a%'` — эффективно)
**С чем НЕ поможет:**
- Поиск четных или нечетных чисел.
- Поиск суффиксов (`LIKE '%c'` — неэффективно).
## Поиск в B-tree
Алгоритм поиска аналогичен [[Бинарное дерево поиска|бинарному дереву]], но выбор осуществляется из нескольких вариантов, а не из двух. Поиск выполняется за `O(t logt(n))`, но количество обращений к диску — `O(logt(n))`.
Рассмотрим пример поиска значения `5`. Начинаем с корневого блока, он всегда один. 5 больше 1, но меньше 7, поэтому идем в левую часть индекса.
![[../../../meta/files/images/Pasted image 20241104203100.png]]
Видим, что 5 больше чем 4, поэтому идем по ссылке на 4
![[../../../meta/files/images/Pasted image 20241104203423.png]]
И там уже мы находим нашу 5.
![[../../../meta/files/images/Pasted image 20241104203446.png]]
А пятерка в свою очередь указывает на место в таблице, и мы можем достать оттуда данные.
![[../../../meta/files/images/Pasted image 20241104203517.png]]
Значения в узлах могут быть не уникальными. Например, если значение `5` встречается дважды, поиск продолжается, переходя в следующий узел. Чтобы облегчить этот процесс, блоки на одном уровне связаны, создавая связный список.
## Добавление в B-tree
Представим, что нужно вставить значение `15` в уже существующее дерево.
![](../../../meta/files/images/Pasted%20image%2020240129194120.png)
Вставка должна произойти между значениями `4` и `17`. Узел `7...16` переполнен (t = 3, максимум 5 значений), поэтому узел разбивается начиная с `t-1` элемента (в данном случае `11`). Элемент, по которому происходит разбиение, перемещается в родительский узел. Если родительский узел переполняется, он тоже разбивается, и так далее.
После вставки мы получим следующее дерево
![](../../../meta/files/images/Pasted%20image%2020240129194629.png)
## Удаление из B-tree
Удаление элемента из B-tree требует поддержания минимального количества ключей в узле для сохранения сбалансированности дерева и его эффективной высоты. Например, при удалении элемента, если количество ключей в узле становится меньше `t-1`, выполняется перераспределение элементов из соседних узлов или их слияние, чтобы поддерживать сбалансированность. Существует несколько сценариев удаления:
- **Удаление из листового узла**: Если элемент находится в листовом узле и после его удаления остается не менее `t-1` элементов, узел остается без изменений.
- **Удаление из внутреннего узла**: Если удаляемый элемент находится во внутреннем узле, он заменяется на наибольший элемент в левом поддереве или наименьший элемент в правом поддереве. После этого выполняется удаление из листового узла.
- **Перераспределение и слияние узлов**: Если после удаления в узле остается меньше `t-1` элементов, выполняется перераспределение элементов из соседнего узла или слияние с соседним узлом.
***
## Мета информация
**Область**:: [[../../../meta/zero/00 Разработка|00 Разработка]], [[../../../meta/zero/00 Алгоритм|00 Алгоритм]]
**Родитель**:: [[Tree]]
**Источник**::
**Автор**::
**Создана**:: [[2024-01-29]]
### Дополнительные материалы
-
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->