ГоловнаСтаттіАлгоритми

B-Дерева: Індекс, що стоїть за кожною базою даних

Вузли з сотнями ключів, розділення по середньому ключу, яке просувається вгору, і висота, яка майже не є деревом.

mysimulator teamОновлено — червень 2026≈ 8 хв читання▶ Відкрити симуляцію

Дерево, створене для повільного зберігання

Чорно-біле дерево оптимізоване для мінімізації порівнянь у пам’яті. Б-дерево (Байєр і МакКрейт, 1972) оптимізоване для чогось зовсім іншого: мінімізації кількості дискових операцій читання, які значно повільніші за будь-які порівняння в пам’яті. Замість одного ключа на вузол, Б-дерево порядку m містить багато ключів у кожному вузлі – достатньо, щоб заповнити точно одну дискову сторінку або кеш-лінію, тому що одна повільна операція читання одночасно витягує інформацію на тисячі порівнянь.

order m B-tree, every non-root node holds:
  between ceil(m/2) - 1  and  m - 1   keys
  between ceil(m/2)      and  m       children (internal nodes)

keys inside a node are sorted; the k+1 children of a node with k keys
"straddle" the k keys, so child[i] holds keys strictly between
key[i-1] and key[i]

Вставка: заповнення, розділення біля медіани, підняття

Новий ключ вставляється у відповідний лист, зберігаючи його відсортованість. Якщо цей лист тепер містить m ключів – на один занадто багато – він ділиться: середній ключ переміщується до батьківського вузла, а ключі з обох боків від нього стають двома окремими частково повними вузлами.

insert(ключ): лист = find_leaf(ключ) вставити ключ у лист, зберігаючи його відсортованість while лист.keyCount == m: // переповнено, потрібно розділити mid = лист.keys[m / 2] // середній ключ лівий, правий = розділити лист навколо mid якщо у листа немає батьківського вузла: створити новий корінь з mid, діти [лівий, правий] // дерево зростає на рівень +1 інакше: вставити mid у лист.parent, замінити лист на [лівий, правий] лист = лист.parent // розділення може поширюватися вгору Ключовим моментом є те, що B-дерево росте лише вгору, шляхом розділення кореня, тому кожен лист завжди знаходиться на абсолютно тій самій глибині – немає листа, який глибший за інший, на відміну від незбалансованого бінарного дерева.

insert(key):
  leaf = find_leaf(key)
  insert key into leaf, keeping it sorted
  while leaf.keyCount == m:               // overfull, must split
    mid = leaf.keys[m / 2]                 // median key
    left, right = split leaf around mid
    if leaf has no parent:
      create new root with mid, children [left, right]  // tree grows +1 level
    else:
      insert mid into leaf.parent, replace leaf with [left, right]
      leaf = leaf.parent                   // the split may cascade upward
жива демонстрація · пов'язана симуляція● LIVE

Чому висота майже не має відношення до логарифмічного

Висота B-дерева становить O(log_m n), де основа логарифма – це розгалужувальний фактор m, а не 2. Червоно-чорне дерево з мільйоном ключів має висоту приблизно 2·log2(1,000,000) ≈ 40. B-дерево порядку 200, що зберігає той самий мільйон ключів, має висоту приблизно log_200(1,000,000) ≈ 2,6 – практично 3 рівні. Ця різниця є основною причиною існування B-дерев: при достатньо великому m, що відповідає розміру дискової сторінки або кеш-лінії, будь-яку базу даних з мільйонами або мільярдами рядків можна шукати в 3 або 4 дискових операціях читання, а верхні один чи два рівні зазвичай залишаються постійно кешованими в RAM, що робить більшість пошуків більш дешевими на практиці.

B+ дерева та B* дерева

Майже жодна виробнича база даних не використовує простий B-дерево; майже всі використовують B+ дерево. Різниця полягає в тому, що внутрішні вузли B+ дерева зберігають копії ключів лише для маршрутизації пошуків, тоді як весь фактичний обсяг даних знаходиться в листах, а листки з'єднані ланцюжком. Цей ланцюжок перетворює запит відсоркованого діапазону — "надати всі рядки між X та Y" — на одноразову прогулянку деревом разом із швидким боковим ходом по пов’язаних листах, замість повторних повних проходів дерева. B* дерево йде ще далі, відкладаючи розщеплення: коли вузол переповнюється, він спочатку намагається перерозподілити ключі з сусідом, лише тоді, коли обидва сусідні вузли також повні, і розділяє два повні вузли на три вузли, частково заповнені третиною, замість двох вузлів, частково заповнених. Це зберігає вузли більш повною (приблизно 2/3 замість 1/2) за рахунок більшої складності вставки.

Frequently asked questions

Чому бази даних використовують B-дерева замість дерева червоних-чорних?

Дерево червоних-чорних має один ключ на вузол і читає один вузол з диска на порівняння, що для таблиці з мільйоном рядків означає приблизно 20 повільних операцій пошуку по диску. B-дерево пакує сотні ключів у кожному вузлі, розміщених відповідно до розміру сторінки диска, тому кожен запит читання з диска порівнюється з сотнями ключів одночасно. Для того ж мільйона рядків потрібно лише 3 або 4 операції читання з диска, оскільки гілковий коефіцієнт дерева — а не кількість ключів — визначає висоту.

Яка різниця між B-деревом і B+ деревом?

У простому B-дереві ключі та пов’язані з ними дані знаходяться як у внутрішніх, так і в зовнішніх вузлах. У B+ дереві всі дані знаходяться лише в зовнішніх вузлах, внутрішні вузли зберігають копії ключів виключно для маршрутизації, а зовнішні вузли з’єднані ланцюжком. Цей ланцюжок зовнішніх вузлів дозволяє B+ дереву виконувати швидкий відсортований обхід діапазону, переміщаючись в стороні замість повторного проходження дерева, тому майже всі індекси баз даних у виробництві є B+ деревами, а не класичними B-деревами.

Чому кожен зовнішній вузол повинен бути на одній глибині?

Це властивість, яка забезпечує гарантований пошук O(log n) у B-дереві: кожен пошук проходить точно на висоту, визначену кількістю вузлів, незалежно від того, який ключ шукається. B-дерево підтримує це, ростучи вгору — новий рівень додається лише тоді, коли корінь розщеплюється — замість того, щоб рости вниз і залишати деякі зовнішні вузли глибшими за інші.

Спробуйте наживо

Усе, що вище, працює прямо у вашому браузері — відкрийте B-Trees і змінюйте параметри під час роботи. Нічого не встановлюється, нічого не завантажується на сервер, уся модель живе в одній вкладці.

▶ Відкрити симуляцію B-Trees

Що ви знайшли?

Додати кроки відтворення (опційно)