B-Tree ve B+ Tree nedir? Ekleme, bölme (split), silme, birleştirme (merge) işlemleri, B+ Tree farkları ve veritabanı indeksleme mantığı — görsellerle anlatım.
B-Tree ve B+ Tree nedir? Ekleme, bölme (split), silme, birleştirme (merge) işlemleri, B+ Tree farkları ve veritabanı indeksleme mantığı — görsellerle anlatım.
Neden B-Tree? — Disk Erişim Problemi
Şimdiye kadar öğrendiğimiz ağaçlar (BST, AVL, RB) RAM'de çalışmak üzere tasarlanmıştır. Bir düğüme erişmek nanosaniyeler sürer. Ancak veritabanları ve dosya sistemleri verilerini diskte saklar — ve disk erişimi dramatik şekilde yavaştır.
| Depolama | Erişim Süresi | Hız Farkı |
|---|---|---|
| L1 Cache | ~1 ns | 1× |
| RAM | ~100 ns | 100× |
| SSD | ~100 μs | 100.000× |
| HDD | ~10 ms | 10.000.000× |
Bir AVL ağacında 1 milyon anahtar varsa yükseklik ~20'dir. Her arama 20 düğüm erişimi gerektirir — RAM'de sorun olmaz ama diskte 20 ayrı disk okuması demektir. Çözüm: her düğüme çok sayıda anahtar koyarak ağacın yüksekliğini düşürmek. İşte B-Tree'nin temel fikri budur.
AVL ile 1.000.000 anahtar
Arama = 20 disk I/O
20 × 10ms = 200ms
B-Tree (t=500) ile 1.000.000 anahtar
Arama = 3 disk I/O
3 × 10ms = 30ms
B-Tree Kuralları
B-Tree, minimum derece t (t ≥ 2) parametresiyle tanımlanan, kendiliğinden dengeli çok yollu arama ağacıdır. 1970'te Rudolf Bayer ve Edward McCreight tarafından geliştirilmiştir.
Sayısal Örnekler
| Parametre | Formül | t=2 | t=3 | t=500 |
|---|---|---|---|---|
| Min anahtar | t - 1 | 1 | 2 | 499 |
| Max anahtar | 2t - 1 | 3 | 5 | 999 |
| Min çocuk | t | 2 | 3 | 500 |
| Max çocuk | 2t | 4 | 6 | 1000 |
| Yükseklik (1M kayıt) | logt(n) | ~20 | ~12 | ~2 |
Referans B-Tree (t = 3)
Düğüm Yapısı ve Arama
Ekleme ve Bölme (Insert & Split)
B-Tree'ye ekleme daima bir yaprak düğüme yapılır. Ekleme yapılacak yaprak doluysa (2t-1 anahtar), düğüm ekleme öncesinde bölünür (split). Bölme yukarıya propagate ederek köke kadar çıkabilir — kök bölünürse ağaç yukarıdan büyür.
Bölme (Split) İşlemi — Detay
t=3 olan bir düğümde max 5 anahtar vardır. Düğüm doluysa:
Adım Adım — B-Tree Ekleme (t=3)
Ekleme sırası: 10, 20, 30, 40, 50, 25, 35, 5
Silme ve Birleştirme (Delete & Merge)
B-Tree'den silme, eklemeden çok daha karmaşık bir operasyondur. Temel kısıt: silme sonrası hiçbir düğüm t-1'den az anahtar tutmamalıdır (kök hariç). Bu kısıtı korumak için ödünç alma (redistribution) ve birleştirme (merge) mekanizmaları devreye girer.
Eklemedeki proaktif bölme mantığına benzer şekilde, silmede de proaktif takviye (preemptive fix-up) uygulanır: kökten yaprağa inerken yolumuzun üzerindeki her düğümün en az t anahtarı olduğundan emin oluruz. Böylece yaprağa ulaştığında güvenle silebiliriz.
3 Temel Silme Durumu
Durum 1: Yapraktan Doğrudan Silme
Durum 2: İç Düğümden Silme
Durum 3: Yetersiz Düğüm (Underflow)
Durum 2 Detay — Öncül ve Ardıl
İç düğümden silinen anahtar ki için iki seçenek vardır:
② Ardıl (in-order successor): ki'nin sağ alt ağacındaki en küçük anahtar (en soldaki yaprakta en soldaki anahtar). Sağ çocuğun ≥ t anahtarı varsa bu strateji kullanılır.
③ Her ikisi de minimum ise: Sol ve sağ çocuk birleştirilir (merge), sonra birleştirilmiş düğümde rekürsif olarak silinir.
Durum 3 Detay — Underflow Düzeltme Stratejileri
Silme yolundaki bir çocuk düğümde tam t-1 anahtar varsa, silme yapılırsa kural bozulur. İki düzeltme mekanizması vardır:
Adım Adım — Kapsamlı Silme Örneği
Başlangıç ağacı (t=3):
2. Sol çocuk ≥ t (3 anahtar) → öncül stratejisi kullan.
3. Sol alt ağacın en büyüğü = 20 (öncül).
4. 30 ↔ 20 yer değiştirir → 30 artık yaprakta → Durum 1 olarak silinir.
2. Sağ komşu [35, 40, 50] → ≥ t=3 → redistribution (ödünç alma) uygulanabilir.
3. Ebeveynden 20 sol çocuğa iner, sağ komşunun ilk anahtarı (35) ebeveyne çıkar.
4. Sol yaprak artık [5, 10, 20] → 5'i güvenle silebiliriz.
Ekleme ve Silme Kuralları — Özet Tablosu
| Durum | Koşul | Eylem |
|---|---|---|
| Ekleme — yer var | Yaprakta < 2t-1 anahtar | Sıralı pozisyona ekle |
| Ekleme — dolu | Yaprakta 2t-1 anahtar | Split → medyan yukarı, iki yarım düğüm |
| Kök bölme | Kök doluysa | Yeni kök oluştur → yükseklik +1 |
| Silme — Durum 1 | Yaprakta > t-1 anahtar | Doğrudan çıkar |
| Silme — Durum 2 | Anahtar iç düğümde | Öncül/ardıl ile değiştir → yaprağa taşı |
| Silme — Durum 3a | Çocuk minimum, komşu > min | Redistribution (ödünç al) |
| Silme — Durum 3b | Çocuk minimum, komşu da minimum | Merge → ebeveynden anahtar al |
| Kök merge | Kök boşalırsa | Kökü kaldır → yükseklik -1 |
B+ Tree — Veritabanlarının Gerçek Tercihi
B-Tree kavramsal olarak mükemmeldir, ancak gerçek dünya veritabanlarının büyük çoğunluğu (MySQL/InnoDB, PostgreSQL, SQLite, Oracle, SQL Server) B-Tree'nin bir varyantı olan B+ Tree kullanır. B+ Tree, B-Tree'nin disk I/O ve aralık sorgusu zayıflıklarını çözer.
B-Tree vs B+ Tree — 3 Kritik Fark
Fark 1: Veri Nerede?
B+ Tree: Veri sadece yapraklarda. İç düğümler sadece yol gösterici anahtar (index key) tutar.
Fark 2: Yaprak Bağlantısı
B+ Tree: Yapraklar bağlı liste (linked list) ile birbirine bağlı → sıralı tarama (range scan) çok hızlı.
Fark 3: Anahtar Tekrarı
B+ Tree: İç düğümlerdeki anahtarlar yapraklarda tekrar eder. İç düğümler "kopyalar" — asıl veri yaprakta.
B+ Tree Yapısı — Görsel
B+ Tree'nin Avantajları — Neden Veritabanları Tercih Eder?
B-Tree vs B+ Tree — Detaylı Karşılaştırma
| Özellik | B-Tree | B+ Tree |
|---|---|---|
| Veri konumu | Her düğümde | Sadece yapraklarda |
| İç düğümler | Anahtar + veri | Sadece anahtar (index) |
| Yaprak bağlantısı | Yok ✗ | Bağlı liste ✓ |
| Anahtar tekrarı | Yok (benzersiz) | İç düğümler yaprakta tekrar |
| Fan-out (dallanma) | Orta | Çok yüksek ✓ |
| Ağaç yüksekliği | Orta | Daha düşük ✓ |
| Arama derinliği | Değişken (1..h) | Sabit (h) ✓ |
| Nokta sorgusu | Hızlı ✓ (erken durabilir) | Hızlı ✓ (yaprak) |
| Aralık sorgusu | Yavaş (inorder) ✗ | Çok hızlı (bağlı liste) ✓ |
| Sıralı tarama | Rastgele I/O ✗ | Sıralı I/O ✓ |
| Bellek kullanımı | Daha az düğüm | Yaprak tekrarı (biraz fazla) |
| Kullanım alanı | Dosya sistemleri, genel amaçlı | Veritabanları, index ✓ |
Aralık Sorgusu — B+ Tree vs B-Tree
2. Inorder: ebeveyne çık → sağ çocuğa in
3. Her adımda farklı disk sayfası
4. Rastgele disk I/O — yavaş!
2. Bağlı listede → yürü:
20 → 25 → 30 → 35 → dur
3. Sıralı disk I/O — çok hızlı!
B+ Tree Düğüm Yapısı
Veritabanı İndeksleme Mantığı
Bir veritabanı tablosunda milyonlarca satır olduğunda, SELECT * FROM users WHERE id = 42 sorgusu index olmadan tüm tabloyu taramak zorundadır (full table scan — O(n)). İndeks, arama süresini O(n) → O(log n) düşüren bir veri yapısıdır. Ve bu indeksin arkasında B+ Tree vardır.
İndeks Olmadan vs İndeks İle
Full Table Scan (İndeks Yok)
→ 10.000.000 satır oku
Disk sayfası ~100 satır → 100.000 disk I/O
~1000 saniye (HDD)
B+ Tree İndeks İle
→ 3-4 disk sayfası oku
+ 1 veri sayfası okuma
~40ms (HDD) / ~0.4ms (SSD)
Clustered vs Non-Clustered (Secondary) İndeks
• Tablo başına sadece 1 adet (çünkü veri tek sırada olabilir)
• Genellikle PRIMARY KEY üzerinde otomatik oluşur
• Yaprak = asıl tablo satırı
• MySQL/InnoDB: her tablo bir clustered index'tir
• Yapraklar satır yerine satır adresini (pointer) tutar
• Tablo başına birden fazla olabilir
• Arama: index → pointer → asıl satır (ekstra I/O)
• CREATE INDEX ile oluşturulur
SQL İndeks Oluşturma Örnekleri
• Tablonun küçük kısmı değil, çoğu okunuyorsa (full scan daha hızlı)
• Sütun üzerinde fonksiyon uygulanırsa: WHERE YEAR(date) = 2024 → index atlanır
• Düşük seçicilik (selectivity): cinsiyet gibi sadece 2 değer → B+ Tree verimsiz
• LIKE '%abc' → önek olmadan (wildcard başta) index kullanamaz
Veritabanlarında B+ Tree Kullanımı
| Veritabanı | İndeks Yapısı | Sayfa Boyutu | Notlar |
|---|---|---|---|
| MySQL / InnoDB | B+ Tree (clustered) | 16 KB | Tablo = clustered index. PK yoksa gizli row ID üzerinde B+ Tree. |
| PostgreSQL | B+ Tree (varsayılan) | 8 KB | Heap table + ayrı B+ Tree index'ler. GiST, GIN, BRIN alternatifleri. |
| SQLite | B+ Tree | 4 KB | Tek dosyalı DB. rowid üzerinde B+ Tree. |
| Oracle | B+ Tree (varsayılan) | 8 KB | IOT (Index-Organized Table) = clustered B+ Tree. |
| SQL Server | B+ Tree | 8 KB | Clustered + non-clustered index'ler. |
| MongoDB | B+ Tree (WiredTiger) | ~4 KB | Doküman ID üzerinde varsayılan B+ Tree index. |
Gerçek Dünya Disk Sayfası Hesabı
Bir sayfaya sığan anahtar: 16384 / 14 ≈ 1170 anahtar (fan-out)
Seviye 1 (kök): 1 sayfa → 1170 anahtar, 1171 çocuk
Seviye 2: 1171 sayfa → 1170 × 1171 ≈ 1.370.000 anahtar
Seviye 3: 1171² sayfa → 1170 × 1171² ≈ 1.6 milyar anahtar
→ 1.6 milyar kayıt, sadece 3 disk I/O ile erişilebilir!
Karmaşıklık Analizi
| Operasyon | B-Tree | B+ Tree | Disk I/O |
|---|---|---|---|
| Arama (nokta) | O(logt n) | O(logt n) | O(logt n) |
| Ekleme | O(t × logt n) | O(t × logt n) | O(logt n) |
| Silme | O(t × logt n) | O(t × logt n) | O(logt n) |
| Aralık sorgusu (k sonuç) | O(k × logt n) | O(logt n + k) | O(logt n + k/B) |
| Sıralı tarama (tümü) | O(n) | O(n) — sıralı I/O ✓ | O(n/B) |
| Min / Max | O(logt n) | O(logt n) | O(logt n) |
B+ Tree vs Diğer Yapılar — Genel Karşılaştırma
| Yapı | Arama | Aralık | Ekleme | Disk I/O | Kullanım |
|---|---|---|---|---|---|
| Hash Index | O(1) | Yapamaz ✗ | O(1) | 1 I/O | = eşitlik sorgusu |
| AVL / RBTree | O(log n) | O(log n + k) | O(log n) | O(log n) ✗ | RAM içi |
| B-Tree | O(logt n) | O(k logt n) | O(logt n) | O(logt n) | Dosya sistemi |
| B+ Tree | O(logt n) | O(logt n+k) ✓ | O(logt n) | O(logt n) ✓ | Veritabanı ✓ |
| LSM-Tree | O(log n) | O(log n + k) | O(1) ort. | Yazma optimize | NoSQL (Cassandra) |
Gerçek Dünya Kullanımları
| Alan | B-Tree / B+ Tree Kullanımı |
|---|---|
| İlişkisel Veritabanları | MySQL, PostgreSQL, Oracle, SQL Server — tüm index'ler B+ Tree |
| NoSQL Veritabanları | MongoDB (WiredTiger), CouchDB — doküman index'leme |
| Dosya Sistemleri | NTFS, HFS+, ext4 (htree), Btrfs (adında B-Tree var!) — dosya/dizin araması |
| Key-Value Depoları | BoltDB, LMDB, LevelDB — B+ Tree veya LSM-Tree |
| Arama Motorları | Inverted index (ters çevrilmiş indeks) altında B+ Tree |
| GIS / Coğrafi Sorgular | R-Tree (B-Tree'nin çok boyutlu genellemesi) |
Sonuç
B-Tree ve B+ Tree, disk tabanlı depolama için tasarlanmış kendiliğinden dengeli çok yollu ağaçlardır. Temel motivasyon: disk erişimi RAM'den 100.000+ kat yavaştır — ağaç yüksekliğini düşürerek disk I/O sayısını minimize etmek gerekir. Her düğüm bir disk sayfası (4-16 KB) kadar veri tutarak yüzlerce dallanma sağlar → milyarlarca kayıt sadece 3-4 seviyeye sığar.
B+ Tree, B-Tree'nin veritabanı optimize edilmiş versiyonudur. İç düğümler sadece yol gösterici anahtar tutar (daha fazla dallanma), tüm veri yapraklardadır ve yapraklar bağlı liste ile birbirine bağlıdır (aralık sorguları için sıralı I/O). Bu yüzden MySQL, PostgreSQL, Oracle, SQLite gibi tüm modern veritabanları B+ Tree kullanır.
İndeksleme, veritabanı performansının en kritik konusudur. Doğru sütunlara doğru index'ler koymak, sorgu süresini saniyelerden milisaniyelere düşürebilir. Ama gereksiz index'ler yazma performansını olumsuz etkiler (her INSERT/UPDATE'de B+ Tree güncellenmeli). Denge: okuma ağırlıklı sorgularda index çok faydalı, yazma ağırlıklı iş yüklerinde dikkatli olunmalı.