Hash Index, SQL Server’ın “hız canavarı” olan Bellek İyileştirilmiş Tablolarda (In-Memory Tables) kullanılan, veriye adeta “ışınlanmanızı” sağlayan özel bir indeks türüdür. Klasik indeksler gibi sayfalar arasında gezmez, bir matematiksel formül kullanarak verinin yerini nokta atışı bulur.
Eşittir (=) operatörü kullanıldığında SQL Server’daki en hızlı erişim yöntemidir. Hızlı performans sunar. Özellikle “Şu değer şuna eşittir” (WHERE Kolon = Değer) şeklindeki sorgular için tasarlanmıştır.
Sadece In-Memory OLTP (RAM üzerinde çalışan tablolar) için geçerlidir; standart disk tabanlı tablolarda kullanılamaz.
Hash Index Nasıl Çalışır?
İşleyişi bir kütüphanedeki akıllı robot gibi düşünebilirsin:
- Sen bir değer verdiğinde (örneğin ID = 101), SQL Server bunu bir matematiksel formüle (algoritma) sokar ve ona özel bir “adres kodu” (Hash değeri) üretir.
- Bu adres kodu, bellekte önceden ayrılmış binlerce küçük kutudan (Bucket) hangisine gidileceğini söyler.
- Sorgu attığında sistem tüm tabloyu taramaz; formülü çalıştırır, ilgili “kovayı” bulur ve içindeki veriyi anında çeker.
- Eğer iki farklı veri (tesadüfen) aynı kovaya düşerse yani Çakışma (Collision) olursa, SQL Server kovanın içine kısa bir göz atarak doğru kaydı seçer. Bu yüzden kova sayısı doğru ayarlanmalıdır.
Hash Index’in Avantajları
- Özellikle devasa veri kümelerinde WHERE Kolon = Değer sorgularında rakipsizdir.
- Kova sayısını (bucket_count) manuel belirleyebildiğin için RAM kullanımını doğrudan kontrol edebilirsin.
- Karmaşık matematiksel işlemler tamamen SQL Server’ın sorumluluğundadır; sen sadece verimliliğin tadını çıkarırsın.
Hash Index’in Dezavantajları
- Hash değerleri matematiksel olarak rastgele dağıldığı için >, <, BETWEEN veya ORDER BY gibi işlemler için tamamen kullanışsızdır.
- Eğer iki farklı anahtar aynı kovaya düşerse, SQL Server ek bir “ayıklama” işlemi yapar. Bu da performansın bir miktar düşmesi demektir.
- İndeksi oluştururken belirlediğin kova sayısı sonradan değiştirilemez. Hatalı bir sayı seçersen performansı düzeltmek için indeksi silip en baştan yapman gerekir.
- Sadece Memory-Optimized (Bellek İyileştirilmiş) tablolar için üretilmiştir, standart disk tablolarında çalışmaz.
Eğer tablonun %90’ı “eşittir” sorgusu alıyor ama arada bir “şu aralıktaki verileri getir” diyorsan, tabloya hem bir Hash Index (eşittir sorguları için) hem de bir Non-Clustered Index (aralık sorguları için) ekleyebilirsin. SQL Server sorguna göre en iyisini kendisi seçecektir.
BUCKET_COUNT seçimi, bir Hash Index’in kalbidir. Yanlış bir sayı seçmek, Ferrari motoruna sahip bir arabayı trafik sıkışıklığına sokmaya benzer.
İşte kova sayısını belirlerken izlemen gereken altın kurallar ve teknik formül:
Kova sayısı, sütundaki benzersiz (unique) değer sayısına eşit veya onun bir miktar üzerinde olmalıdır.
- Benzersiz değer sayısının 1 ila 2 katı arasıdır.
- Eğer tablonuzda 1 milyon farklı MusteriID olacaksa, BUCKET_COUNT değerini 1.000.000 ile 2.000.000 arasında bir değer yapmalısınız.
SQL Server, kova sayısını dahili olarak her zaman 2’nin kuvvetlerine (2, 4, 8, 16, 32…) yuvarlar.
Siz BUCKET_COUNT = 100.000 yazsanız bile SQL Server bunu otomatik olarak bir üst kuvvet olan 131.072‘ye tamamlar. Bu yüzden belirlediğiniz sayının 2’nin kuvveti olması performansı öngörülebilir kılar.
| Durum | Sonuç | Etkisi |
| Çok Düşük (Under-sizing) | Hash Collision (Çakışma) | Çok fazla veri aynı kovaya dolar. SQL aradığınızı bulmak için kova içinde liste tarar. Performans ciddi oranda düşer. |
| Çok Yüksek (Over-sizing) | Bellek İsrafı | Her kova bellekte 8 byte yer kaplar. Milyonlarca boş kova, GB’larca RAM’in boşa gitmesi demektir. |
Diyelim ki bir Urunler tablonuz var ve yaklaşık 500.000 farklı ürününüz olacağını öngörüyorsunuz.
-- 500.000'in bir üstündeki 2'nin kuvveti 524.288'dir.
CREATE TABLE Urunler
(
UrunID INT NOT NULL PRIMARY KEY NONCLUSTERED HASH WITH (BUCKET_COUNT = 524288),
UrunAd NVARCHAR(100) NOT NULL
) WITH (MEMORY_OPTIMIZED = ON);
Eğer bir tablonuz varsa ve kova sayısının yeterli olup olmadığını anlamak istiyorsanız şu sorguyu kullanabilirsiniz:
SELECT
quotient AS [Doluluk Oranı], -- %100'e yakın olmalı
avg_chain_length AS [Ortalama Zincir Uzunluğu], -- 1'e yakın olmalı, 10'un üzerindeyse kova sayısı azdır!
max_chain_length AS [En Uzun Zincir]
FROM sys.dm_db_xtp_hash_index_stats(OBJECT_ID('TabloAdiniz'));
Özetle: Tahmin ettiğin satır sayısının biraz fazlasını hedefle ve 2’nin kuvvetlerini kullanmaya çalışılması gerekmektedir. Eşitlik sorguları açısından, hash index genellikle geleneksel nonclustered indekslerden daha hızlıdır. Ancak hash index’in dar bir kullanım alanı olduğu ve belirli durumlarda diğer indeks türleriyle birlikte kullanılması gerektiği unutulmamalıdır
Bu makalede Hash Index konusuna değinmiş olduk. Başka bir makalede görüşmek dileğiyle.
De ki: “Şüphesiz benim namazım, ibadetlerim, dirimim ve ölümüm alemlerin Rabbi olan Allah’ındır.” En’am Suresi, 162. Ayet
