← Назад к вопросам
Как устроен B-tree индекс?
1.8 Middle🔥 111 комментариев
#Архитектура и паттерны#Базы данных (SQL)
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
B-tree индекс: структура и механизм
B-tree (сбалансированное дерево) — это фундаментальная структура данных, используемая в базах данных и файловых системах для создания индексов. Это многоуровневое дерево поиска, оптимизированное для работы с дисковой памятью.
Основные характеристики B-tree
- Сбалансированность — все листья находятся на одинаковом уровне, что гарантирует логарифмическую сложность поиска O(log n)
- Степень (order) — каждый узел может содержать до m потомков и m-1 ключей
- Многоуровневость — структурирована иерархически, что минимизирует количество обращений к диску
- Опсеченность — каждый узел может быть неполностью заполнен, но должен содержать минимальное количество элементов
Структура узла B-tree
Узел B-tree содержит:
┌─────────────────────────────────────────┐
│ K1 | K2 | K3 | ... | Km-1 │ Ключи
├─────────────────────────────────────────┤
│ P0 | P1 | P2 | P3 | ... | Pm │ Указатели на потомков
└─────────────────────────────────────────┘
где:
- K1 < K2 < K3 < ... < Km-1
- P0 ведёт к узлам с ключами < K1
- P1 ведёт к узлам с ключами между K1 и K2
- Pm ведёт к узлам с ключами > Km-1
Пример B-tree порядка 3 (m=3)
[25, 50]
/ | \
/ | \
[10, 15] [30, 40] [60, 70]
/ | \ / | \ / | \
5 12 20 35 45 55 65 75 80
Операции в B-tree
Поиск элемента:
def search_btree(node, key):
"""
Поиск ключа в B-tree с начала с корня.
Временная сложность: O(log n)
"""
i = 0
# Найти первый ключ, который >= искомому
while i < len(node.keys) and key > node.keys[i]:
i += 1
# Если найден точный ключ
if i < len(node.keys) and key == node.keys[i]:
return node # Найдено!
# Если это лист, ключа нет
if node.is_leaf:
return None
# Рекурсивный поиск в потомке
return search_btree(node.children[i], key)
Вставка элемента:
def insert_btree(tree, key):
"""
Вставка нового ключа в B-tree.
При переполнении узел расщепляется.
"""
root = tree.root
# Если корень полный, создаём новый корень и расщепляем
if is_full(root):
new_root = Node()
new_root.is_leaf = False
new_root.children.append(root)
split_child(new_root, 0)
tree.root = new_root
insert_non_full(tree.root, key)
def insert_non_full(node, key):
"""Вставка в неполный узел."""
i = len(node.keys) - 1
if node.is_leaf:
# Простая вставка в лист
node.keys.append(None)
while i >= 0 and key < node.keys[i]:
node.keys[i + 1] = node.keys[i]
i -= 1
node.keys[i + 1] = key
else:
# Найти потомка для вставки
while i >= 0 and key < node.keys[i]:
i -= 1
i += 1
# Расщепить потомка если нужно
if is_full(node.children[i]):
split_child(node, i)
if key > node.keys[i]:
i += 1
insert_non_full(node.children[i], key)
Удаление элемента:
def delete_btree(node, key):
"""
Удаление ключа из B-tree.
Более сложная операция, требует балансировки.
"""
if node.is_leaf:
# Простое удаление из листа
node.keys.remove(key)
else:
# Удаление из внутреннего узла
# ... сложная логика с перемещением ключей ...
pass
Почему B-tree предпочтительны для БД?
- Минимизация обращений к диску — узлы часто соответствуют блокам на диске, большой порядок означает меньше уровней
- Сбалансированность — гарантированное O(log n) для всех операций
- Эффективность дисковых операций — последовательное чтение блокирует минимум операций I/O
- Поддержка range queries — легко получить диапазон значений благодаря сортировке
B+ tree vs B-tree
B+ tree — вариант B-tree, где:
- Все ключи хранятся в листах
- Внутренние узлы содержат только указатели
- Листья связаны в отсортированный список
B+ tree структура:
[25, 50]
/ | \
[10-20][25-40][60-75] <- листья с данными
|-------|-------|----- <- связный список листьев
Примеры использования в реальных БД
- PostgreSQL — B-tree индексы по умолчанию для большинства типов данных
- MySQL/InnoDB — B+ tree для индексов
- SQLite — B-tree для всех индексов
- MongoDB — B-tree индексы для _id и других полей
B-tree индексы — критически важны для производительности баз данных, обеспечивая быстрый поиск, вставку и удаление при минимальном количестве обращений к диску.