Berk Akademi
Birebir ders başvurusu Ücretsiz ön görüşme Ana Sayfa

SQL sorgusunda indeks neden kullanılmıyor? EXPLAIN rehberi

sql-sorgusunda-indeks-neden-kullanilmiyor-explain-rehberi
Bu yazıda neler var?
  1. İndeks Varken Veritabanı Neden Başka Planı Seçer?
  2. Tam Tablo Taraması mı, İndeks Taraması mı?
  3. WHERE Koşulları ve Birleşik İndeks Sütun Sırası
  4. EXPLAIN Çıktısında Hangi Sinyallere Bakılır?
  5. Tarih Sütunundaki Fonksiyon Nasıl İndeks Dostu Hâle Getirilir?
  6. Beş Adımda İndeks Kullanımı Teşhisi
  7. Sık Sorulan Sorular

SQL sorgusunda indeks neden kullanılmıyor? Bir indeksin mevcut olması, veritabanının onu her sorguda kullanacağı anlamına gelmez. Planlayıcı; koşulun kaç satır döndüreceğini, tablonun boyutunu, satırlara erişim maliyetini ve istatistikleri değerlendirerek indeksli ya da tam taramalı planlardan tahmini maliyeti daha düşük olanı seçebilir.

Bu nedenle “indeks var ama sorgu hızlanmadı” durumunda ilk adım yeni indeks eklemek değil, EXPLAIN ile seçilen planı ve filtre koşulunu incelemektir. EXPLAIN sözdizimi ve plan terimleri veritabanı motoruna göre değişebileceği için aşağıdaki açıklama ortak mantığı, plan örnekleri ise şematik gösterimi kullanır.

İndeks Varken Veritabanı Neden Başka Planı Seçer?

İlk ölçüt seçiciliktir. Seçicilik, bir koşulun tablodaki satırların ne kadar küçük bir bölümünü eşleştirdiğini anlatır. Örneğin tek bir müşteriye ait kayıtları aramak genellikle az sayıda satır döndürürken, çok sayıda kaydın aynı durumu taşıdığı bir koşul daha düşük seçiciliğe sahiptir. Planlayıcı, koşulun kaç satır döndüreceğini tahmin eder; eşleşen satır sayısı arttıkça indeks üzerinden tek tek kayıtlara ulaşmanın avantajı azalabilir.

Tablo boyutu da önemlidir. Küçük bir tabloda tüm satırları art arda okumak, önce indekse gidip ardından tablodaki satırlara dönmekten daha düşük maliyetli olabilir. Büyük bir tabloda ise yalnızca az sayıda satırın gerektiği koşullarda indeks erişimi daha uygun görülebilir. Bu, kesin bir kural değildir; verilerin fiziksel yerleşimi, veri dağılımı ve motorun maliyet modeli sonucu değiştirebilir.

Sorgu biçimi de indeksi etkiler. İndeksli sütuna YEAR(created_at) benzeri bir fonksiyon uygulamak, normal sütun indeksinden doğrudan yararlanmayı zorlaştırabilir. Benzer şekilde, karşılaştırılan iki değerin veri türleri farklıysa motor dönüşüm yapmak zorunda kalabilir. Bu dönüşümün indeksi kullanmayı engelleyip engellemediği, ilgili motorun ifade çözümleme ve indeksleme davranışına bağlıdır.

İstatistikler güncel değilse planlayıcı veri dağılımını yanlış tahmin edebilir. Sonuç olarak az satır döndüreceğini düşündüğü bir sorgu için indeks yolunu, gerçekte çok sayıda satır döndüren bir sorgu içinse tam taramayı seçebilir. Örneğin PostgreSQL belgeleri plan maliyetini tahmini bir değer olarak açıklar ve planlayıcının tahmini toplam maliyeti düşük planı aradığını belirtir; MySQL belgeleri de maliyet tabanlı optimizasyonun bazı durumlarda tablo taramasını daha ucuz bulabileceğini ifade eder.

Bu nedenle indeksi kullanmayan planı otomatik olarak “hatalı” kabul etmeyin. Önce sorguyu ve planı okuyun; benzer teknik açıklamalar için Berk Akademi blog arşivindeki yazılım ve veri tabanı içeriklerine göz atabilirsiniz.

Tam Tablo Taraması mı, İndeks Taraması mı?

Tam Tablo Taraması mı, İndeks Taraması mı?

Basit bir sorgu düşünelim:

SELECT order_id
FROM orders
WHERE customer_id = 42;

Tam tablo taramasında motor, tablodaki satırları doğrudan okuyup her satırda customer_id = 42 koşulunu kontrol eder. İndeks yolunda ise önce customer_id indeksinde ilgili değeri arar, ardından indeksten bulunan aday satırlara ulaşır. Beklenen sonuç az sayıda satırsa ikinci yol avantajlı olabilir.

Plan A — tam tablo taraması
  Tabloyu oku
  Her satırda filtreyi kontrol et
  Tahmini eşleşme: çok sayıda

Plan B — indeks yolu
  İndekste customer_id = 42 değerini ara
  Bulunan satırlara git
  Tahmini eşleşme: az sayıda

Ancak çok sayıda satır eşleştiğinde indeks yolu, indeks ile tablo arasında çok sayıda erişim gerektirebilir. Küçük tablolarda da tam tarama daha makul olabilir. Veri dağılımı, satırların fiziksel yerleşimi, istatistiklerin güncelliği ve motorun maliyet tahminleri birlikte değerlendirilmelidir. Bu yüzden indeks eklemeden önce ve sonra aynı sorguyu ölçün; yalnızca EXPLAIN planının değişmesine değil, gerçek çalışma süresine ve okunan veri miktarına da bakın. PostgreSQL ve MySQL belgeleri, planların tahminlere dayandığını ve tablo taramasının bazı veri kümelerinde daha düşük maliyetli seçilebildiğini gösterir.

WHERE Koşulları ve Birleşik İndeks Sütun Sırası

İndeksin kullanılabilmesi, yalnızca indeksin varlığına değil, WHERE koşulunun indekslenmiş sütunla nasıl karşılaştırıldığına da bağlıdır. Doğrudan eşitlikler ve aralık koşulları, özellikle B-tree indekslerde, sorgu planlayıcısının değerlendirebildiği tipik koşullardır: durum = 'aktif', puan >= 70 veya olusturma_tarihi < '2026-09-01' gibi.

Birden fazla filtre bulunduğunda bütün koşulların aynı şekilde indekse taşınacağını varsayma. Bazı koşullar indeks üzerinden aday satırları daraltırken bazıları satırlar bulunduktan sonra uygulanabilir. Sütunu bir fonksiyonla sarmalamak, örneğin LOWER(kullanici_adi) = 'berk', normal sütun indeksinin doğrudan eşleşmesini zorlaştırabilir. PostgreSQL bu tür sorgular için ifade indekslerini destekler; ancak bunun ayrı bir indeks tasarımı olduğunu unutma.

Örtük veri türü dönüşümleri de ayrıca incelenmelidir. Uygulama bir sayısal sütunu metin parametresiyle, tarih sütununu uyumsuz bir türle karşılaştırıyorsa veritabanı operatör ve dönüşüm seçimini kendisi yapar. PostgreSQL belgeleri, karışık türlerde ifadelerin dönüşüm kurallarıyla çözüldüğünü belirtir. Bu nedenle karşılaştırılan sütun ile parametrenin veri türlerini mümkün olduğunca eşleştir; plan içinde beklenmeyen dönüşüm veya fonksiyon görürsen sorguyu sadeleştirerek yeniden ölç.

Birleşik indekste sütun sırası, sorgunun filtrelediği alanlarla birlikte düşünülmelidir. Örneğin (musteri_id, durum, olusturma_tarihi) indeksinde, musteri_id ve durum üzerinden eşitlik koşulları bulunan bir sorgu, indeksin önde gelen sütunlarını daha etkili kullanabilir. Buna karşılık yalnızca sondaki tarih sütununu filtrelemek aynı avantajı garanti etmez. Bu, bütün veritabanı motorları ve bütün indeks türleri için değişmez bir kural değildir; PostgreSQL B-tree belgelerinde de öndeki sütunlara getirilen kısıtların indeks tarama alanını daraltmada daha belirleyici olduğu açıklanır.

Teşhis öncesinde gereksiz sütunları, tekrar eden koşulları ve kullanılmayan filtreleri ayıkla. Aynı sorguyu farklı parametrelerle denemek de önemlidir; seçicilik ve veri dağılımı değiştiğinde planlayıcının tercihi değişebilir.

EXPLAIN Çıktısında Hangi Sinyallere Bakılır?

EXPLAIN Çıktısında Hangi Sinyallere Bakılır?

EXPLAIN çıktısını yalnızca “indeks kullanıldı” veya “kullanılmadı” şeklinde okumak eksik kalır. Önce erişim yoluna, ardından tahmini satır sayısına, filtreye ve maliyete bak. Sıralama, birleştirme ve toplama adımları da sorgunun toplam maliyetini etkileyebilir.

Aşağıdaki çıktı gerçek bir veritabanı motoruna ait değildir; alanların nasıl yorumlanacağını göstermek için hazırlanmış şematik bir karşılaştırmadır:

Plan A
  Access Path: Sequential Scan
  Estimated Rows: 48,000
  Filter: status = 'active'
  Cost: 72.00

Plan B
  Access Path: Index Scan
  Estimated Rows: 1,200
  Filter: status = 'active'
  Cost: 96.00

Bu örnekte indeksli plan daha az satır buluyor görünse de maliyeti daha yüksek tahmin edilmiştir. Filtre tablonun büyük bir bölümünü döndürüyor, tablo küçük kalıyor veya indeks üzerinden bulunan satırlar için tabloya çok sayıda ayrı erişim gerekiyorsa tam tablo taraması daha uygun olabilir. Yani “indeks var” bilgisi tek başına karar verdirmez.

PostgreSQL’de EXPLAIN planlayıcının tahmini maliyetini ve plan düğümlerini gösterir; ANALYZE seçeneği ise sorguyu gerçekten çalıştırarak gerçek süre ve satır sayılarını ekler. Tahmini satır sayısı ile gerçek satır sayısı ciddi biçimde ayrışıyorsa veri dağılımı, istatistikler veya parametre değerleri yeniden incelenmelidir. Maliyet birimi de doğrudan milisaniye değildir.

Son olarak, EXPLAIN sözdizimi, alan adları ve plan terimleri veritabanı motoruna göre değişir. Buradaki Access Path, Estimated Rows, Filter ve Cost alanları okuma çerçevesidir; kendi motorunun resmî plan belgelerindeki karşılıklarıyla doğrulanmalıdır.

Tarih Sütunundaki Fonksiyon Nasıl İndeks Dostu Hâle Getirilir?

Tarih sütununa DATE(), CAST() veya saat dilimi dönüşümü gibi bir fonksiyon uygulandığında, veritabanı motoru sütundaki mevcut indeksi doğrudan aralık erişimi için değerlendirmeyebilir. Bu kesin bir kural değildir; bazı motorlar fonksiyon sonucunu indeksleyen ifade tabanlı indeksleri destekler. Ancak bu, normal created_at indeksinden farklı bir tasarımdır.

-- Temsili: günün kayıtlarını fonksiyonla filtreleme
SELECT order_id, created_at
FROM orders
WHERE DATE(created_at) = :gun;

-- Aynı aralığı sütunu doğrudan karşılaştırarak kurma
SELECT order_id, created_at
FROM orders
WHERE created_at >= :baslangic
  AND created_at < :bitis;

İkinci biçim, başlangıç sınırını dâhil edip bitiş sınırını hariç tutan yarı açık bir tarih aralığı oluşturur. Böylece gün sonu için yapay bir 23:59:59 değeri üretme ve hassasiyet kaybı yaşama ihtiyacı azalır. Bununla birlikte, :baslangic ve :bitis parametrelerinin veri tipi, tarih literal yazımı ve saat dilimi anlamı kullandığın motora göre doğrulanmalıdır. Tarih, timestamp ve zaman dilimli tarih-saat türlerinin davranışı motorlar arasında farklılaşabilir.

EXPLAIN çıktısı şematik olarak şu niteliksel farkı gösterebilir; gerçek plan terimleri motora göre değişir:

Önce:  [tam tablo taraması] -> Filter: DATE(created_at) = :gun

Sonra: [aralık erişimi?]     -> created_at >= :baslangic
                              created_at <  :bitis

        Tahmini satır sayısı: daha dar olabilir

İlk planda çok sayıda satır okunup daha sonra elenebilir. İkinci planda ise uygun koşullarda indeks üzerinden aralık erişimi plan seçenekleri arasına girebilir. Bu, indeksin kesin olarak seçileceği veya belirli bir performans yüzdesi sağlayacağı anlamına gelmez; seçicilik, tablo boyutu, istatistikler, veri dağılımı ve motorun maliyet hesabı birlikte değerlendirilir.

Beş Adımda İndeks Kullanımı Teşhisi

Teşhisi şu sırayla yürütmek, rastgele yeni indeks eklemekten daha sağlıklı bir başlangıç sağlar. SQL'e geçmeden önce programlama ve algoritmik düşünme temellerini kontrol etmek istersen, Berk Akademi'nin ücretsiz yazılım ve algoritmik düşünme bilgi testlerinden yararlanabilirsin.

  1. Sorguyu sadeleştir. Önce yalnızca gerekli tabloyu, sütunları ve filtreyi bırakarak sorguyu küçült. Temsili ve gerçekçi parametreler kullan. Sorun devam ediyorsa EXPLAIN aşamasına geç.
  2. EXPLAIN al. Komutun yazımı ve ayrıntılı çıktı biçimi motora göre değişir. Önce tahmini planı incele; destekleniyorsa gerçek çalışma bilgisi sunan seçenekle gerçek satır sayısını ve süreyi ölç. PostgreSQL ve MySQL belgeleri, bu tür analiz seçeneklerinin sorguyu çalıştırabildiğini belirtir.
  3. Filtreyi incele. Koşulun indeks erişiminde mi, yoksa satırlar okunduktan sonraki filtreleme aşamasında mı uygulandığına bak. Çok sayıda satır okunup az sayıda satır dönüyorsa bir sonraki adımda ifade yapısını kontrol et.
  4. Fonksiyon ve dönüşüm ara. İndeksli sütunun fonksiyonla sarılması, örtük veri türü dönüşümü veya saat dilimi çevrimi var mı kontrol et. Bulursan sütunu doğrudan karşılaştıran bir koşul ve sütunla uyumlu parametre türleri dene.
  5. Planı yeniden ölçüp karşılaştır. Aynı sorguyu, karşılaştırılabilir parametrelerle ve mümkün olduğunca aynı ortamda tekrar çalıştır. Erişim yolunu, tahmini ve gerçek satır sayılarını, süreyi ve mevcutsa okuma ölçümlerini karşılaştır. Yalnızca plan metninin değişmesine bakma.

Son karar, yalnızca “indeks kullanıldı mı?” sorusuna indirgenmemelidir. Sorgu yazımı, istatistiklerin güncelliği, veri dağılımı, seçicilik ve mevcut indeksin gerçekten gerekli olup olmadığı birlikte değerlendirilmelidir. Bu incelemeler yapılmadan eklenen indeks, yazma maliyetini artırıp sorunu çözmeden kalabilir.

Sık Sorulan Sorular

İndeks varken tam tablo taraması görülmesi her zaman hata mıdır?

Hayır. Sorgu tablonun büyük bölümünü döndürüyor, tablo küçükse veya indeksin seçiciliği düşükse tam tablo taraması daha uygun maliyetli olabilir. Kararı EXPLAIN planı ve gerçek ölçümle değerlendirmek gerekir.

EXPLAIN içindeki tahmini satır sayısı ile gerçek satır sayısı neden farklı olabilir?

Tahminler istatistiklere ve veri dağılımı varsayımlarına dayanır. İstatistiklerin güncelliğini yitirmesi, verinin dengesiz dağılması, birden fazla koşulun birlikte etkisi ve parametre değerleri tahmin ile gerçek sonucu ayırabilir.

Birleşik indekste sütunların sırası sorgu performansını nasıl etkiler?

Sütun sırası, motorun indeksin hangi ön bölümünü daraltabileceğini etkiler. Sorguda birleşik indeksin başındaki sütunlar kullanılmıyorsa indeksin tam seçiciliği kullanılamayabilir; kesin davranış indeks türüne ve motora göre değişir.

Tarih sütununa uygulanan her fonksiyon indeks kullanımını kesin olarak engeller mi?

Hayır. Motor, ifade tabanlı indeksleri veya özel optimizasyonları destekleyebilir. Ancak normal sütun indeksinin kullanılacağını varsaymak yerine, ilgili sorgunun EXPLAIN planını ve veri türü dönüşümlerini kontrol etmek gerekir.

İndeks sorunlarında en güvenilir yaklaşım, sorguyu sadeleştirip planı ölçmek ve sonucu veri yapısıyla birlikte değerlendirmektir.

Bu içerik aradığın cevabı verdi mi?
Yanıtın, hangi yazıları geliştirmemiz gerektiğini anlamamıza yardımcı olur.
Bu içeriğin üretilmesinde yapay zeka araçlarından destek alınmıştır.

Bu konudan sonra ne okuyabilirsin?

Tüm yazılar

İlgili Eğitimler

Berk Keskin, yazılım geliştirici ve eğitmen
Yazar

Berk Keskin Kimdir?

Yazılıma 12 yaşında başladı; İzmir Ekonomi Üniversitesi'ni bölüm birincisi ve yüksek şeref öğrencisi olarak tamamladı. Bugün yalnızca eğitim vermekle kalmıyor, sektörde aktif olarak yazılım projeleri geliştiriyor ve gerçek dünya deneyimini birebir derslerine taşıyor. Ezberden uzak, mühendislik zihniyetini merkeze alan sürdürülebilir öğrenme sistemleri tasarlayarak sorgulayan, üreten ve problem çözebilen yeni nesil yazılımcılar yetiştiriyor.

Sektörel Deneyim & Projeler

  • Ticarify Entegrasyon Yazılım logosu CEO Ticarify Entegrasyon YazılımPazaryerleri ve e-ticaret sitelerine otomatik e-fatura kesimi, sipariş ve kargo takibi hizmetleri sunan e-Dönüşüm platformunun API mimarisini ve yazılım ekibini yönetmektedir.
  • Benim Düğünüm logosu CEO Benim DüğünümDijital etkinlik ve anı paylaşım platformu.
  • Siberdizayn logosu Yazılım Ekibi Lideri SiberdizaynYüksek anlık oyuncu trafiğine sahip oyun kontrol panelleri ve sunucu altyapıları geliştiren yazılım ekibine liderlik etmektedir.
  • MEDYOGRAFYA 360° Dijital Çözümler logosu Dijital Strateji Lideri MEDYOGRAFYA 360° Dijital ÇözümlerŞirketlerin dijital çözümlerde uzun vadede nasıl ilerlemesi gerektiği ve dijital dönüşüm süreçlerinin yönetilmesine destek olmaktadır.
  • İzmir Ekonomi Üniversitesi logosu Danışma Kurulu Üyesi İzmir Ekonomi ÜniversitesiMezun olduğu üniversitesinde, Bilgisayar Programcılığı bölümünün akademik müfredatını güncel sektör ihtiyaçlarına göre şekillendirmek adına Danışma Kurulu'nda görev almaktadır.
WhatsApp Hemen Ara