aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Web Geliştirme

Veritabanı İndeks Nedir, Ne Zaman ve Nasıl Kullanılır

Bir veritabanı indeks, tablodaki satırları belirli bir sütun ya da sütun grubuna göre sıralı tutan ek bir veri yapısıdır; tıpkı bir kitabın sonundaki dizin gibi, aradığın değeri sayfa sayfa taramak yerine doğrudan bulmanı sağlar. Uygulamanız büyüdükçe "neden bu sorgu yavaşladı?" sorusunun cevabı genellikle eksik ya da yanlış kurulmuş bir indekstir. Bu yazıda indekslerin sorguları nasıl hızlandırdığını, hangi maliyetleri getirdiğini ve ne zaman kullanılması gerektiğini somut örneklerle anlatıyorum.

İndeks olmadan ne olur: tam tablo taraması

İndeks olmayan bir sütunda arama yaptığınızda veritabanı tam tablo taraması (full table scan) yapmak zorunda kalır: satırları baştan sona tek tek okur ve koşula uyanları toplar. 1.000 satırlık bir tabloda bu fark edilmez, ama 5 milyon satırda her sorgu diskten milyonlarca satır okumak demektir.

SELECT * FROM users WHERE email = 'aslain@example.com';

email sütununda indeks yoksa, motor tek bir satırı bulmak için tüm tabloyu gezer. Karmaşıklık kabaca O(n)'dir: satır sayısı arttıkça süre doğrusal büyür. İndeks varsa arama O(log n)'e iner — milyonlarca satırda devasa bir fark.

İndeks aslında nasıl çalışır: B-tree

İlişkisel veritabanlarındaki klasik indeks bir B-tree (daha doğrusu B+tree) yapısıdır. Değerler sıralı şekilde dallara yerleştirilir; her arama kökten yapraklara doğru ilerler ve her adımda olası satırların yarısından fazlasını eler. Bu yüzden milyonlarca kayıt arasında bile aradığınız değere yalnızca birkaç adımda ulaşırsınız.

  • Eşitlik aramaları (=) ve aralık aramaları (<, >, BETWEEN) B-tree'de hızlıdır.
  • Sıralama (ORDER BY) ve gruplama indeks zaten sıralı olduğu için bedavaya gelebilir.
  • LIKE 'aslain%' gibi önek aramaları indeksten faydalanır; ama LIKE '%aslain' (baştan joker) faydalanamaz.

Metin içinde arama (full-text) ya da coğrafi sorgular için B-tree yerine farklı indeks türleri kullanılır; örneğin tam metin için FULLTEXT indeksleri.

İndeks kurmak ve etkisini ölçmek

Tek sütunlu bir indeks oluşturmak basittir:

CREATE INDEX idx_users_email ON users (email);

Gerçekten çalışıp çalışmadığını tahmin etmeyin — ölçün. MySQL ve PostgreSQL'de EXPLAIN komutu, sorgunun planını gösterir:

EXPLAIN SELECT * FROM users WHERE email = 'aslain@example.com';

MySQL çıktısında type sütunu ALL ise tam tarama yapılıyordur (kötü); ref ya da const ise indeks kullanılıyordur (iyi). rows değeri motorun taramayı beklediği satır sayısını verir; indeks doğru kurulduğunda bu sayı dramatik düşer.

Bileşik indeksler ve "en soldan" kuralı

Birden fazla sütunu birlikte sorgularken bileşik (composite) indeks kullanılır. Sütun sırası kritiktir, çünkü B-tree değerleri verdiğiniz sırayla sıralar:

CREATE INDEX idx_orders_user_status
  ON orders (user_id, status);

Bu indeks WHERE user_id = 5 ve WHERE user_id = 5 AND status = 'paid' sorgularını hızlandırır. Ama tek başına WHERE status = 'paid' sorgusunu hızlandırmaz — buna en soldan önek (leftmost prefix) kuralı denir. Bir telefon rehberini önce soyada, sonra ada göre düşünün: yalnızca adı bilerek hızlı arama yapamazsınız.

İpucu: en seçici (en çok ayrıştırıcı) ve eşitlikle sorgulanan sütunu sola, aralık koşullarını sağa koyun.

Maliyetler: indeks bedava değildir

İndeks her sorunu çözen sihirli bir düğme değildir; somut maliyetleri vardır:

  • Yazma yavaşlar: Her INSERT, UPDATE ve DELETE işleminde ilgili indekslerin de güncellenmesi gerekir. Bir tabloda 10 indeks varsa, her ekleme 10 ek yapı güncellemesi demektir.
  • Disk ve bellek tüketir: İndeksler ayrı yer kaplar; çok sayıda gereksiz indeks veritabanını şişirir ve önbelleği kirletir.
  • Düşük seçicilikte işe yaramaz: Yalnızca iki değeri olan bir sütunda (örneğin is_active) indeks çoğu zaman fayda sağlamaz; motor zaten tam tarama yapmayı tercih eder.

Bu yüzden kural basittir: okuma çok, koşul seçici ise indeksle; her sütuna körlemesine indeks ekleme.

Pratik öneriler

  • Birincil anahtarlar (PRIMARY KEY) ve benzersiz kısıtlar zaten indekslidir; tekrar indekslemeyin.
  • JOIN ve WHERE koşullarında sık kullanılan yabancı anahtar sütunlarını indeksleyin.
  • ORDER BY ile sürekli sıraladığınız sütunları indeks adayı olarak değerlendirin.
  • Yavaş sorguları bulmak için slow query log'u açın, sonra EXPLAIN ile doğrulayın.
  • Kullanılmayan indeksleri belirleyip silin; bakım da optimizasyonun parçasıdır.

Sık Sorulan Sorular

Her sütuna indeks eklemek iyi bir fikir mi?

Hayır. Gereksiz indeksler yazma işlemlerini yavaşlatır, disk yer kaplar ve sorgu planlayıcısını şaşırtabilir. Yalnızca gerçekten sorgulanan, seçiciliği yüksek sütunları indeksleyin ve kararınızı EXPLAIN ile doğrulayın.

İndeks sorgumu neden hâlâ hızlandırmadı?

Sık nedenler: sütunu bir fonksiyona soktunuz (WHERE YEAR(created_at) = 2026 indeksi devre dışı bırakır), bileşik indekste en soldan kuralını çiğnediniz, ya da sütunun seçiciliği çok düşük. EXPLAIN çıktısı genellikle sebebi gösterir.

Birincil anahtar ile indeks aynı şey mi?

Birincil anahtar özel bir indekstir: hem benzersizdir hem de boş değer (NULL) kabul etmez ve çoğu motorda tablonun fiziksel sıralamasını (clustered index) belirler. Yani her birincil anahtar bir indekstir, ama her indeks birincil anahtar değildir.

Veritabanınız yavaşlıyor ve nedenini bulamıyor musunuz? Sorgularınızı analiz edip doğru indeks stratejisini kurabilir, kötü çalışan sorguları yeniden yazabilirim. Yardım için benimle iletişime geçin.

Bu kategorideki tüm yazılar →

Devamı için