Modern yazılım sistemlerinde veri hacmi büyüdükçe, bu veriye erişim hızı uygulamanın genel performansını doğrudan etkiler. Milyonlarca satırdan oluşan bir tabloda aradığınız tek bir kullanıcıyı veya siparişi bulmak, doğru yapılandırma olmadığında sistem kaynaklarını tüketebilir. İlişkisel veritabanı yönetim sistemlerinde bu sorunun temel çözümü indeks yapılarıdır.
Veritabanında İndeks Mantığı
Veritabanı indeks yapısını anlamanın en bilinen yolu, basılı bir kitabın arkasındaki fihrist bölümünü düşünmektir. Bin sayfalık teknik bir kitapta belirli bir kavramı aradığınızda, ilk sayfadan başlayıp son sayfaya kadar tüm yaprakları tek tek kontrol etmezsiniz. Bunun yerine kitabın sonundaki alfabetik fihriste gider, ilgili kavramın hangi sayfalarda geçtiğini öğrenir ve doğrudan o sayfaya atlarsınız.
Veritabanlarında indeks bulunmadığında, bir sorguyu çalıştırmak için sistem tablodaki tüm satırları baştan sona okumak zorunda kalır. Bu işleme tam tablo taraması (Full Table Scan) adı verilir. Küçük tablolarda bu durum fark edilmeyecek kadar hızlı gerçekleşse de, veri boyutu yüz binleri veya milyonları aştığında disk okuma işlemleri (I/O) tavan yapar ve sorgu süreleri kabul edilemez seviyelere çıkar.
İndeks, tablonun belirli sütunlarındaki verileri özel bir veri yapısı içinde, sıralı ve işaretçilerle (pointers) birlikte tutan ayrı bir yapıdır. Böylece veritabanı motoru aranan veriyi bulmak için tüm tabloyu değil, yalnızca bu optimize edilmiş yapıyı inceler.
İndeks Nasıl Çalışır?
İlişkisel veritabanlarının büyük çoğunluğunda indeksler varsayılan olarak B-Tree (Balanced Tree / Dengeli Ağaç) veri yapısı kullanılarak oluşturulur. B-Tree mimarisi, veriyi hiyerarşik bir ağaç şeklinde düğümlere (node) ayırır.
Ağacın en üstünde kök düğüm (root), ortasında dallar (branches) ve en altında yaprak düğümler (leaves) bulunur. Bir arama işlemi gerçekleştirildiğinde, veritabanı motoru kök düğümden başlar ve aranan değerin büyüklük-küçüklük durumuna göre dallar üzerinden yapraklara doğru ilerler. Bu yöntem sayesinde arama karmaşıklığı doğrusal zamandan (O(N)), logaritmik zamana (O(log N)) düşer.
Örneğin, bir milyon satırlık bir tabloda doğrusal arama yapıldığında en kötü senaryoda bir milyon işlem gerekirken, dengeli bir B-Tree yapısında aranan kayda yaklaşık 20 adımda ulaşılabilir.
Temel İndeks Türleri
Veritabanı sistemleri farklı sorgu senaryolarına yönelik çeşitli indeks türleri sunar.
Clustered Index (Kümelenmiş İndeks)
Kümelenmiş indeks, tablodaki verilerin disk üzerindeki fiziksel depolama sırasını belirler. Bir kitap örneğine dönersek, kitabın sayfalarının 1’den başlayarak sıralı gitmesi kümelenmiş indekstir.
- Bir tabloda yalnızca bir adet kümelenmiş indeks bulunabilir; çünkü veriler fiziksel olarak aynı anda sadece bir kurala göre sıralanabilir.
- Genellikle birincil anahtar (Primary Key) tanımlandığında veritabanı yönetim sistemi bu sütun üzerinde otomatik olarak bir kümelenmiş indeks oluşturur.
Non-Clustered Index (Kümelenmemiş İndeks)
Kümelenmemiş indeks, tablonun fiziksel sıralamasını değiştirmez. Bunun yerine, aranan sütun değerini ve bu değerin asıl tabloda nerede durduğunu gösteren bir işaretçiyi (Row ID veya Clustered Key) barındıran ayrı bir yapı kurar.
- Bir tabloda birden fazla kümelenmemiş indeks tanımlanabilir.
- Kitabın sonundaki fihrist yapısının tam karşılığıdır.
Composite (Bileşik) İndeks
Birden fazla sütunun bir araya getirilmesiyle oluşturulan indeks türüdür. Sık sık birlikte filtrelenen sütunlar için kullanılır.
- Sütunların indeks tanımındaki yazılış sırası kritiktir (Leading Column prensibi).
- Örneğin (ad, soyad) şeklinde kurulan bir indeks; yalnızca ada göre yapılan veya hem ad hem soyada göre yapılan aramalarda çalışır, ancak yalnızca soyada göre yapılan aramalarda doğrudan kullanılamaz.
SQL ile İndeks Kullanımı
İndeks kavramını somutlaştırmak için örnek bir kullanıcı tablosu üzerinden ilerleyelim.
Aşağıdaki komut, test amaçlı bir kullanicilar tablosu oluşturur:
CREATE TABLE kullanicilar (
id INT PRIMARY KEY,
ad VARCHAR(50),
soyad VARCHAR(50),
eposta VARCHAR(100),
kayit_tarihi DATE
);
Bu tabloda id sütunu birincil anahtar olduğu için sistem tarafından otomatik olarak kümelenmiş indeks ile donatılmıştır. Ancak kullanıcıları e-posta adreslerine göre sorgulamak istediğimizde bu indeks işe yaramaz.
E-posta sütununa göre yapılan aramaları hızlandırmak için kümelenmemiş bir indeks oluşturalım:
CREATE INDEX idx_kullanicilar_eposta ON kullanicilar (eposta);
Bu komut, eposta sütunundaki değerleri sıralı bir B-Tree yapısında tutan idx_kullanicilar_eposta adlı bağımsız bir yapı inşa eder.
Eğer kullanıcıları hem ad hem de soyada göre filtreleyen sorgular yazıyorsak, bileşik bir indeks tanımlayabiliriz:
CREATE INDEX idx_kullanicilar_ad_soyad ON kullanicilar (ad, soyad);
Bu indeks, aşağıdaki sorgunun performansını doğrudan artırır:
SELECT * FROM kullanicilar WHERE ad = 'Ahmet' AND soyad = 'Yılmaz';
Sorgunun indeksi kullanıp kullanmadığını doğrulamak için veritabanlarında EXPLAIN veya EXPLAIN ANALYZE komutu kullanılır:
EXPLAIN SELECT * FROM kullanicilar WHERE eposta = 'ornek@alanadi.com';
Bu komutun çıktısında tarama türü olarak Index Scan veya Index Seek ifadesini görmek, sorgunun tüm tabloyu gezmek yerine oluşturduğumuz indeksi kullandığını doğrular.
İndeks Kullanımının Maliyetleri ve Dikkat Edilmesi Gerekenler
İndeksler okuma (SELECT) performansını önemli ölçüde artırsa da tamamen maliyetsiz değillerdir. Yanlış veya gereksiz indeks kullanımı sistem üzerinde ters etki yaratabilir.
- Disk Alanı: Her indeks, veritabanı dosya sisteminde ek depolama alanı kaplar. Büyük tablolarda indeks boyutu, tablonun asıl verisinden daha fazla yer tutabilir.
- Yazma Performansı: Tabloya yeni bir kayıt eklendiğinde (INSERT), bir kayıt silindiğinde (DELETE) veya indeksli sütun güncellendiğinde (UPDATE), veritabanı motoru yalnızca ana tabloyu değil, o sütuna bağlı tüm indeks yapılarını da güncellemek zorundadır. Bu durum yazma işlemlerini yavaşlatır.
- Düşük Seçicilik (Low Cardinality): Cinsiyet veya aktiflik durumu gibi az sayıda benzersiz değer içeren sütunlarda B-Tree indeksi oluşturmak genellikle performansı artırmaz. Veritabanı motoru bu tür durumlarda indeks yerine tüm tabloyu okumayı tercih edebilir.
Özet ve Sonraki Adımlar
Veritabanı indeks mekanizması, doğru sütunlara ve doğru sorgu modellerine uygulandığında sistem yanıt sürelerini saniyelerden milisaniyelere düşürebilen kritik bir optimizasyon aracıdır. Ancak her sütunu indekslemek yerine, sık filtrelenen, sıralanan (ORDER BY) veya birleştirilen (JOIN) sütunları hedeflemek gerekir.
Sonraki adım olarak, veritabanınızdaki yavaş sorguları tespit etmek için yavaş sorgu günlüklerini (Slow Query Log) aktif hale getirebilir ve sorgu yürütme planlarını (Execution Plan) okumayı derinleştirebilirsiniz.


Comments
No comments yet. Write the first comment.