Yazılım & Kodlama

SQL Sorgu Optimizasyonu: Yavaş Sorguları EXPLAIN ile Hızlandırmak

Yavaş bir SQL sorgusu, bütün bir uygulamayı dize getirebilir. EXPLAIN çıktısını okumayı, sık görülen tuzakları ve sorguları hızlandırmanın somut tekniklerini bu rehberde ele alıyoruz.

SQL Sorgu Optimizasyonu: Yavaş Sorguları EXPLAIN ile Hızlandırmak

Bir uygulama yavaşladığında ilk suçlanan genellikle sunucu ya da ağdır. Oysa deneyimli geliştiriciler bilir ki sorunun büyük çoğunluğu, hatalı yazılmış veya indeksten yoksun birkaç SQL sorgusunda saklıdır. Tek bir kötü sorgu, sayfa yükleme süresini saniyelere çıkarabilir ve trafik arttığında veritabanını kilitleyebilir. İyi haber şu: SQL optimizasyonu bir kara sanat değildir; ölçülebilir, öğrenilebilir ve tekrarlanabilir bir disiplindir. Bu yazıda, yavaş sorguları nasıl bulacağınızı, EXPLAIN çıktısını nasıl okuyacağınızı ve somut hızlandırma tekniklerini ele alıyoruz.

SQL Sorgu Optimizasyonu: Yavaş Sorguları EXPLAIN ile Hızlandırmak
API tasarımı ve geliştirme

Önce Ölçün: Tahminle Optimizasyon Yapılmaz

Optimizasyonun altın kuralı, tahmin etmemektir. "Bu sorgu yavaştır herhalde" demek yerine, hangi sorgunun gerçekten yavaş olduğunu ölçmek gerekir. MySQL'de yavaş sorgu günlüğü (slow query log) bu iş için biçilmiş kaftandır:

SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;
-- 1 saniyeden uzun süren sorgular kaydedilir

Bu günlüğü birkaç gün açık bıraktığınızda, uygulamanızın gerçek darboğazları kendini gösterir. Çoğu zaman "en yavaş" sorgu değil, "en sık çalışan ve orta yavaşlıktaki" sorgu asıl yükü oluşturur.

Optimizasyonda içgüdü yanıltıcıdır. Bir sorguyu hızlandırmaya başlamadan önce, onun gerçekten sorun olduğunu kanıtlayan bir ölçüm elinizde olmalı.

EXPLAIN: Veritabanının Aklını Okumak

EXPLAIN, veritabanının bir sorguyu nasıl çalıştırmayı planladığını gösteren en güçlü aracınızdır. Sorgunun önüne yazdığınızda, hangi tabloların hangi sırayla tarandığını, hangi indekslerin kullanıldığını ve kaç satırın incelendiğini görürsünüz:

EXPLAIN SELECT * FROM siparisler
WHERE musteri_id = 42
ORDER BY olusturma_tarihi DESC;

Çıktıda dikkat etmeniz gereken sütunlar şunlardır:

  • type: Erişim türü. "ALL" (tam tablo taraması) görürseniz alarm zilleri çalmalı; "ref" veya "range" çok daha iyidir, "const" ise mükemmeldir.
  • key: Kullanılan indeks. "NULL" ise hiç indeks kullanılmıyor demektir.
  • rows: Veritabanının inceleyeceğini tahmin ettiği satır sayısı. Bu sayı ne kadar küçükse o kadar iyi.
  • Extra: "Using filesort" veya "Using temporary" ifadeleri, çoğu zaman iyileştirilebilecek bir maliyete işaret eder.

En Sık Görülen Yavaşlık Sebepleri

1. İndekssiz WHERE ve JOIN Koşulları

Bir sorgu tam tablo taraması yapıyorsa, neredeyse her zaman WHERE veya JOIN'de kullanılan sütunda indeks eksiktir. Yukarıdaki örnekte musteri_id üzerinde indeks yoksa, veritabanı tüm siparişleri tek tek gezmek zorunda kalır.

2. SELECT * Alışkanlığı

Yalnızca ihtiyacınız olan sütunları çekmek, hem ağ trafiğini hem de bellek kullanımını azaltır. Daha önemlisi, yalnızca indekste bulunan sütunları çekiyorsanız veritabanı "kapsayan indeks" (covering index) sayesinde tabloya hiç dokunmadan cevap verebilir.

3. Fonksiyon İçine Alınmış Sütunlar

WHERE koşulunda bir sütunu fonksiyona sararsanız, indeks kullanılamaz hale gelir:

-- Kötü: indeks devre dışı kalır
WHERE YEAR(olusturma_tarihi) = 2025

-- İyi: indeks çalışır
WHERE olusturma_tarihi >= '2025-01-01'
  AND olusturma_tarihi < '2026-01-01'

4. N+1 Sorgu Problemi

Bir listeyi çekip sonra her satır için ayrı sorgu atmak, en yaygın performans katilidir. 100 sipariş için 1 + 100 sorgu çalıştırmak yerine, JOIN veya tek bir IN sorgusuyla veriyi toplu çekmek dramatik fark yaratır.

SQL Sorgu Optimizasyonu: Yavaş Sorguları EXPLAIN ile Hızlandırmak
Test odaklı geliştirme

Sorguyu Yeniden Yazmak

Bazen sorun indeks değil, sorgunun kurgusudur. Birkaç etkili teknik:

  1. Alt sorgu yerine JOIN: Korelasyonlu alt sorgular her satır için tekrar çalışır; çoğu zaman bir JOIN'e dönüştürülebilir.
  2. LIMIT ile sayfalama: Büyük sonuç kümelerinde OFFSET yerine "anahtar tabanlı sayfalama" (keyset pagination) kullanmak, derin sayfalarda çok daha hızlıdır.
  3. Gereksiz DISTINCT ve ORDER BY: İhtiyaç yoksa kaldırın; her ikisi de ek sıralama maliyeti getirir.

Bir Vaka: 8 Saniyeden 40 Milisaniyeye

Berasoft'ta devraldığımız bir e-ticaret projesinde, ürün listeleme sayfası 8 saniyede açılıyordu. EXPLAIN çıktısı üç ayrı tabloda tam tablo taraması gösteriyordu. Kategori ve fiyat filtresinde kullanılan sütunlara bileşik bir indeks ekledik, SELECT *'ı ihtiyaç duyulan altı sütunla değiştirdik ve N+1 halinde çalışan görsel sorgusunu tek JOIN'e indirdik. Sonuç 40 milisaniyeye düştü; tek satır sunucu donanımı değiştirmeden.

Bir sorguyu yüzlerce kat hızlandırmak çoğu zaman daha güçlü bir sunucu değil, doğru yerde bir indeks ve daha akıllı bir sorgu ister.

Sonuç

SQL optimizasyonu ölçmekle başlar, EXPLAIN ile anlamak ve doğru indeks ile sorgu yeniden yazımıyla devam eder. Bu döngüyü öğrenen bir ekip, donanım büyütmeden büyük performans kazançları elde eder. Uygulamanız trafikle birlikte yavaşlıyorsa, sorun genellikle çözülebilir birkaç sorguda saklıdır. Var olan bir sistemin veritabanı performansını iyileştirmek isterseniz bizimle iletişime geçebilirsiniz; ölçüp bulup düzeltiriz.

Bu yazıyı paylaş:

Bir sonraki projeniz için hazır mısınız?

Okuduklarınızı işinize uygulamak veya dijital dönüşümünüzü konuşmak isterseniz, ekibimiz bir mesaj uzağınızda.

Görüşler

0 Yorum

İlk yorumu siz yazın.

Yorum Yap

Yorumlar moderatör onayından sonra yayınlanır.