İndeks, bir kitabın arkasındaki dizine benzer: aradığınız kelimeyi bulmak için tüm sayfaları okumak yerine dizine bakıp doğrudan ilgili sayfaya gidersiniz. Veritabanında da mantık aynıdır — ve dizinin kendisinin de yer kapladığı, güncellenmesi gerektiği gerçeği de aynıdır.
Nasıl çalışır
İndeks olmadan bir sorgu tam tarama yapar: tablodaki her satırı okur ve koşula uyanları seçer. Küçük tablolarda sorun değildir; milyonlarca satırda felakettir.
İndeks, belirli bir sütunun değerlerini sıralı bir yapıda tutar ve her değerin hangi satıra karşılık geldiğini gösterir. Çoğu veritabanında bu yapı bir B-ağacıdır.
B-ağacının önemli özelliği, aranan değere birkaç adımda ulaşmasıdır. Milyonlarca satırlık bir tabloda hedefe ulaşmak yalnızca birkaç okuma gerektirir — tabloyu baştan sona taramak yerine.
Sıralı olduğu için aralık sorgularında da işe yarar: belirli bir tarihten sonrası, ya da bir aralıktaki değerler.
Seçicilik belirleyicidir
Her sütuna indeks koymak işe yaramaz. Belirleyici olan seçiciliktir: indeksin sorguyu ne kadar daraltabildiği.
Bir kimlik numarası sütunu son derece seçicidir — her değer neredeyse tek bir satırı gösterir. İndeks burada çok işe yarar.
Buna karşılık yalnızca “evet” ve “hayır” değerleri tutan bir sütun seçici değildir. Aranan değer satırların yarısını kapsıyorsa, veritabanı indeksi kullanmak yerine doğrudan tam tarama yapmayı tercih eder — ve genelde haklıdır, çünkü indeks üzerinden gidip her satır için tabloya dönmek daha pahalıdır.
Bu yüzden “sorgu yavaş, indeks ekleyelim” refleksi her zaman işe yaramaz.
Bileşik indekste sıra önemlidir
Birden çok sütunu kapsayan indekslerde sütun sırası sonucu belirler.
(sehir, tarih) sıralı bir indeks, yalnızca şehre göre yapılan sorgularda da kullanılabilir — çünkü şehir baştadır. Ama yalnızca tarihe göre yapılan bir sorguda kullanılamaz.
Kural şudur: indeks soldan sağa kullanılır. En seçici ve en sık filtrelenen sütun başa konur.
Bu, “indeks var ama kullanılmıyor” durumunun en yaygın nedenidir. Sorgunun filtrelediği sütun, indeksin ortasındaysa devreye girmez.
Sütun üzerinde işlem yapmak indeksi devre dışı bırakır
Az bilinen ama sık karşılaşılan bir tuzak: filtre koşulunda sütuna bir fonksiyon uygulanırsa indeks kullanılamaz.
Bir tarih sütununu yıl bilgisine çevirip karşılaştırmak, ya da bir metin sütununu büyük harfe çevirip aramak bunun tipik örnekleridir. Veritabanı, dönüştürülmüş değeri indekste bulamaz.
Çözüm koşulu yeniden yazmaktır — dönüşümü sütuna değil sabit değere uygulamak, ya da aralık koşuluna çevirmek. Bazı veritabanları ifade üzerinde indeks tanımlamaya da izin verir.
Sorgu yazarken bu ve benzeri desenleri taramak için SQL denetleyici aracı var.
Yazma tarafındaki bedel
İndeks bedava değildir ve bedeli yazma işlemlerinde ortaya çıkar.
Her INSERT, UPDATE ve DELETE işleminde ilgili indekslerin de güncellenmesi gerekir. Bir tabloda on indeks varsa, tek bir satır eklemek on bir ayrı yapıya yazmak demektir.
Ayrıca indeksler yer kaplar. Yoğun indekslenmiş bir tabloda indekslerin toplam boyutu, verinin kendisini geçebilir.
Bu yüzden kullanılmayan indeksleri bulmak ve kaldırmak, indeks eklemek kadar değerli bir bakım işidir. Çoğu veritabanı hangi indeksin ne sıklıkta kullanıldığını raporlar.
Disk tarafındaki karşılığı IOPS nedir yazısında, RAID seviyesinin yazma cezası RAID seviyeleri yazısında.
Kümelenmiş indeks
Bir tabloda kümelenmiş indeks, verinin diskte hangi sıraya göre saklandığını belirler. Bu yüzden tabloda yalnızca bir tane olabilir.
Seçimi önemlidir: sürekli artan bir sütun (kimlik ya da tarih) seçilirse yeni satırlar sona eklenir ve düzen bozulmaz. Rastgele bir değer seçilirse her ekleme araya girmek zorunda kalır, sayfalar bölünür ve performans düşer.
PostgreSQL bu kavramı farklı ele alır; orada tablo düzeni ve şişme yönetimi ayrı bir konudur ve PostgreSQL vacuum ve şişme rehberinde işleniyor.
İstatistikler ve plan
Veritabanı hangi indeksi kullanacağına istatistiklere bakarak karar verir: bir sütunda kaç farklı değer var, dağılım nasıl.
İstatistikler eskidiğinde yanlış karar verilir — var olan bir indeks yok sayılabilir ya da kötü bir birleştirme sırası seçilebilir. Belirti tanıdıktır: sorgu dün hızlıydı, bugün yavaş, ama hiçbir şey değişmedi.
Bu yüzden yavaş bir sorguda ilk bakılacak yer yürütme planıdır — veritabanının ne yapmayı planladığını gösterir. Teşhis sırası yavaş sorgu nereden başlanır rehberinde.
Kısaca
İndeks okumayı hızlandırır, yazmayı yavaşlatır ve yer kaplar. Değerini belirleyen şey seçiciliktir; bileşik indekslerde ise sütun sırası her şeyi değiştirir.
Yavaş bir sorguda refleks olarak indeks eklemeyin. Önce yürütme planına bakın: veritabanı ne yapıyor, neden o yolu seçiyor? Yanıt çoğu zaman eksik indeks değil, indeksi kullanılamaz hâle getiren bir koşuldur.