Rehber 06 Haziran 2026 · 7 dakika okuma

Database Query Optimization: Yavaş sorguları bulma rehberi

Yavaş database sorgularını sistematik bulun: yavaş sorgu logları, EXPLAIN, metrikler ve doğru aksiyon sıralaması.

Yavaş sorgular genellikle “veritabanı yavaş” gibi genel bir ifadeyle geçiştirilir; oysa sorun çoğu zaman belirli bir sorgudan, eksik bir indextan (index), kötü join kurgusundan ya da yanlış istatistiklerden kaynaklanır. Bu rehberde hedefimiz; uygulama tarafında şikâyet gelmeden önce, hangi sorgunun gerçekten yavaşladığını ve neden yavaşladığını hızlıca ortaya çıkarmaktır. Ayrıca sonrasında atılacak adımları (indeks, sorgu yeniden yazımı, çalışma planı doğrulama) net bir sıra ile sunacağız.

Aşağıdaki yöntemler MySQL/MariaDB ve PostgreSQL için uygulanabilir. Elinizde hangi veritabanı olduğu fark etmeksizin, mantık aynıdır: 1) yavaş sorgu sinyalini yakala, 2) sorgunun yürütme planını incele, 3) en büyük maliyeti (en pahalı adımı) hedefle, 4) değişikliği doğrula.


1) Önce hedefi netleştirin: "yavaş" ne demek?

Sorguların yavaşlığı; veritabanı türü, veri hacmi, eşzamanlı istek ve bekleme süreleriyle birlikte değerlendirilmelidir. Tek bir sayı herkes için geçerli değildir, bu yüzden önce ölçüm eşiği belirleyin.

Hedef metrikler

  • Uygulama gecikmesi (örn. endpoint response time)
  • Veritabanı süreleri (örn. query latency)
  • CPU/IO kullanımı (özellikle disk read)
  • Kilit (lock) bekleme süreleri
  • Zaman aşımı (timeout) sayısı

Pratik eşik önerisi (başlangıç için)

  • Çoğu web uygulamasında başlangıç için 100-300 ms üstü sorgular “inceleme adayı”dır.
  • İş yükünüz rapor/analitik ağırlıksa 1-2 sn üstü sorguları hedefleyin.
  • Zaman aşımı alan sorgular zaten en kritik gruptur; önce bunları ele alın.

Net hedef olmadan optimizasyon denemeleri dağılır. Bir sonraki adımda “yakalanabilir” bir iz bırakmanız gerekir.


2) Yavaş sorgu loglarını açın: veri toplayın

Yavaş sorguları bulmanın en hızlı yolu; veritabanının kendi yavaş sorgu loglarına (slow query log / slow log) güvenmektir. Uygulama logları her zaman “tam sorgu” bilgisini taşımaz; DB logları ise doğrudan sorgu metni, çalışma süresi ve çoğu zaman istatistik bilgilerini sağlar.

MySQL / MariaDB için

  • slow_query_log aktif edilmelidir.
  • long_query_time eşiği belirlenmelidir (ör. 0.2 saniye = 200 ms).
  • “Sorguyu” doğru yakalamak için özellikle üretimde mantıklı bir eşik seçin; çok düşük eşik log şişer.

Tipik olarak yapılacak ayar mantığı: - long_query_time: 0.2 - log_output: FILE (veya tablo)

Loglarda genellikle şu alanlar kritik olur: - Query_time (sorgu süresi) - Lock_time (kilit bekleme süresi) - Rows_sent / Rows_examined (varsa)

PostgreSQL için

PostgreSQL’de doğrudan “slow query log” kavramı benzer şekilde çalışır; ayarlar genellikle şu yaklaşım ile yapılır: - log_min_duration_statement değerini belirleyin (örn. 200ms). - Ek olarak kilit/performans gözlemi için ilgili logging seçeneklerini değerlendirin.


Hangi sorgular önce incelenmeli?

Yavaş sorgu loglarından şu sıralamayla ilerleyin: 1. Lock_time yüksek olanlar (lock / bekleme kaynaklı) 2. Aynı sorgunun farklı parametrelerle tekrar ettiği ama her seferinde yavaşlayanlar 3. Rows_examined (veya benzer alan) yüksek olup da sonucunun küçük olduğu sorgular (index eksikliği veya kötü plan) 4. Zaman aşımına giden sorgular

Bu sıralama, “gerçek maliyeti” en hızlı yakalamanızı sağlar.


3) Uygulama tarafında kanıtı bağlayın: endpoint → sorgu

DB logları sorguyu verir; uygulama ise “neden o sorgu çalışıyor?” bağını sağlar. İki veri kaynağını eşleştirmeniz gerekir.

En pratik eşleştirme yöntemi

  • Uygulama tarafında ilgili endpoint’lerin metriklerini toplayın (ör. p95/p99 response time).
  • DB logunda aynı zaman aralığında yavaş sorguları bulup sorgu metnini inceleyin.
  • Uygulama loglarında (request id / trace id varsa) aynı request ile ilişkili sorgu çağrılarını eşleyin.

Eğer observability (OpenTelemetry, APM) kullanmıyorsanız bile temel yaklaşım işe yarar: - Sunucu saatini senkron tutun - DB log zaman aralığı ile uygulama log zaman aralığını çakıştırın


4) EXPLAIN ile çalışmayı görün: planı okumayı öğrenin

Yavaş sorgu bulunduğunda en kritik soru şu: Veritabanı sorguyu nasıl yürütüyor? Çalışma planı (execution plan) burada karar verdirir.

MySQL / MariaDB: EXPLAIN

EXPLAIN çıktısında özellikle şunlara bakın: - type (özellikle ALL = tam tablo taraması) - key (kullanılan index) - rows (tahmini satır sayısı) - possible_keys (kullanılabilecek indexler) - Extra (Using where, Using filesort, Using temporary vb.)

PostgreSQL: EXPLAIN (ANALYZE)

  • EXPLAIN çıktısı “tahmin” verir.
  • EXPLAIN ANALYZE “gerçek çalışma” ile planı netleştirir.

Özellikle şu durumlar problem göstergesidir: - Seq Scan (tam tablo taraması) - Çok sayıda “rows removed by filter” - Hash Join / Nested Loop seçiminin veri boyutlarıyla uyumsuz olması


Plan okuma rehberi: hızlı teşhis tablosu

Aşağıdaki tablo, “hangi belirti hangi soruna gider” eşleşmesini verir.

Gözlenen belirti Muhtemel sebep İlk aksiyon
Tam tablo taraması (MySQL: type=ALL / PostgreSQL: Seq Scan) Index yok veya sorgu indeksi kullanmıyor WHERE ve JOIN kolonlarına index ekle
rows tahmini çok yüksek Kötü istatistik / yanlış sorgu seçimi İstatistikleri güncelle, parametreleri netleştir
filesort / temporary (MySQL) ORDER BY/GROUP BY için uyumsuz index ORDER BY ile aynı sırayı sağlayan index tasarla
Çok fazla satır examine ama az sonuç Seçicilik (selectivity) düşüyor, index filtreyi iyi kullanmıyor Doğru bileşik index veya sorgu yeniden yazımı
Lock_time yüksek Kilit/transaction çatışması Transaction süresini kısalt, izolasyon ayarlarını incele
Nested loop aşırı maliyetli JOIN sırası/koşulları kötü JOIN koşullarını düzenle, uygun index ekle

5) “En pahalı adım” kuralı: optimizasyonu hedefle

Tüm sorguyu baştan yazmaya çalışmak yerine, planın içindeki en pahalı adımı hedefleyin. Mantık şudur: - Sorgu süresi genellikle belirli bir aşamada büyür: geniş tarama, büyük sort, kötü join veya kilit bekleme. - O aşamayı düzeltmek, sorgunun tamamında ölçülebilir fark yaratır.

İndeks ekleme stratejisi (rastgele değil)

İndeks eklemek çoğu zaman en etkili adımdır; ama yanlış indeks: - yazma (INSERT/UPDATE) performansını düşürür, - bakım maliyeti getirir, - yine de sorguyu hızlandırmayabilir.

Bu yüzden indeks tasarımını şu sırayla yapın: 1. Sorgudaki WHERE koşullarını çıkarın 2. JOIN koşullarını çıkarın 3. ORDER BY ve GROUP BY alanlarını çıkarın 4. En sık ve en selektif filtreleyen kolon(lar)ı öne alın 5. Mümkünse bileşik indexi sorgunun ihtiyaç sırasına göre kurgulayın

Bileşik index örneği (mantık)

Örnek (şemayı hayali kabul edin): - WHERE status = ? AND created_at >= ? - ORDER BY created_at DESC

Bu durumda tek kolon indeks yerine, çoğu senaryoda (status, created_at) mantıklı olur; çünkü status filtresi küçültür, created_at ise aralığı ve sıralamayı destekler.

Kesin indeks tasarımı için EXPLAIN çıktısı “index kullanılıyor mu?” sorusunu doğrulamalıdır.


6) Yavaş sorgu bulma sürecini “tekrar edilebilir” hale getirin

Bir defalık analiz yerine, düzenli işleyen bir süreç kurun. En pratik yaklaşım: haftalık/ günlük tarama ve aksiyon listesi.

10 maddelik kontrol listesi

  • [ ] Yavaş sorgu loglarını aktif ve doğru eşiklerle tutun (örn. 200ms)
  • [ ] Logdan ilk 20 sorguyu süreye göre sıralayın
  • [ ] Lock_time yüksek mi kontrol edin (kilit kaynaklı mı?)
  • [ ] Aynı sorgu farklı parametrelerle tekrar ediyor mu?
  • [ ] EXPLAIN ile planı çıkarın
  • [ ] Tam tablo taraması veya sıralama maliyetleri var mı?
  • [ ] Index kullanılıyor mu (key alanı)?
  • [ ] Rows_examined/rows tahmini aşırı yüksek mi?
  • [ ] İndeks veya sorgu değişikliğini test edin (staging)
  • [ ] Değişiklik sonrası planın değiştiğini EXPLAIN ile doğrulayın

Doğrulama olmadan indeks eklemeyin

Değişiklik sonrası iki şeyi karşılaştırın: - Yeni plan: doğru index kullanılıyor mu? - Performans: ortalama değil p95/p99 (uç senaryolar) iyileşti mi?

Ölçüm için sorguyu tek başına denemek yanıltıcıdır. Benzer veri dağılımı ve eşzamanlılıkla test edin.


7) Yaygın sorunlar ve net çözüm yönleri

Yavaş sorgu logu + EXPLAIN sizi kısa yoldan teşhise götürür. Aşağıdaki “en sık” sorunlar, hızlı yönlendirme sağlar.

Sorun: WHERE koşulu index kullanmıyor

Belirti: EXPLAIN’de key NULL veya type ALL. Çözüm yönü: - İlgili kolonlara index ekleyin - Fonksiyonla kolon dönüştürme hatalarını düzeltin (ör. WHERE DATE(col) = ...) - Veri tiplerini (string vs integer) sorgu parametreleriyle uyumlu yapın

Sorun: ORDER BY veya GROUP BY pahalı

Belirti: temporary/filesort. Çözüm yönü: - ORDER BY sırasını destekleyen index tasarlayın - Gerekliyse sonuç setini önce küçültün (doğru filtreleme)

Sorun: Lock bekleme (Lock_time yüksek)

Belirti: Sorgu “yavaş” ama query_time değil lock_time baskın. Çözüm yönü: - Transaction’ı küçültün (işlem bitene kadar kilidi tutmayın) - Büyük update/delete işlemlerini parçalara bölün (batch) - İzolasyon seviyesi ve uzun süren transaction’ları denetleyin

Sorun: JOIN’de yanlış sıra veya eksik index

Belirti: Çok sayıda satır şişiyor, nested loop maliyeti büyüyor. Çözüm yönü: - JOIN anahtar kolonlarına index ekleyin - JOIN koşullarını netleştirin (null/ters eşleşme vb.) - Bazı durumlarda JOIN’i yeniden kurgulamak daha etkilidir


Sonuç: Yavaş sorguyu bulma = ölçüm + plan doğrulama

Yavaş sorgu optimizasyonu, tahminle değil ölçümle ilerler. Önce slow query log ile yavaş sorgu listesini oluşturun, sonra EXPLAIN ile veritabanının gerçekten ne yaptığını görün, en pahalı adımı hedefleyin. Değişiklik sonrası performansı p95/p99 ve plan değişimiyle doğrulayın.

Net aksiyon önerisi: Bugün log eşiğini (örn. 200ms), ilk 20 sorguyu ve lock/query süre dağılımını çıkarın; ardından en pahalı 5 sorgu için EXPLAIN planlarını toplayarak hedefli indeks veya sorgu düzeltmesine geçin. Böyle ilerlediğinizde hem “hangi sorgu” netleşir hem de optimizasyon denemeleri ölçülebilir sonuç verir.

Etiketler: #database #query optimization #yavaş sorgu #index #explain #mysql #postgresql

Hosting karşılaştırması yapmaya hazır mısın?

100+ firmanın fiyatlarını tek tıkla karşılaştır, en uygun paketi bul.

Hosting Karşılaştır →

İlgili Yazılar

0 ürün seçildi