SQL Veri Tabanı Optimizasyon İpuçları
Yavaş bir sayfanın arkasında genellikle tek bir suçlu vardır: kötü yazılmış ya da index'siz bir sorgu. Sunucuya RAM eklemek bunu birkaç ay erteler, çözmez. sql sorgu optimizasyonu ise tahmine değil ölçüme dayandığı için kalıcı sonuç verir. Aşağıdaki adımları kendi veritabanında sırayla uygulayabilirsin; hepsi için gereken tek şey bir SQL istemcisi ve biraz sabır.
Not: örnekler MySQL/PostgreSQL ağırlıklı. Komut adları değişse de mantık her ilişkisel veritabanında aynıdır.
1. Yavaş Sorguyu Bul ve Ne Yaptığını Anla
Optimizasyona sorgu yazarak başlamak yaygın bir hata. Önce hangi sorgunun gerçekten yavaş olduğunu bilmen gerekir. Çoğu projede toplam sürenin büyük kısmını bir avuç sorgu yer.
Ölçmeden başlama: yavaş sorgu kaydı
- MySQL'de slow_query_log'u aç, long_query_time'ı 1 saniyeye çek. Birkaç saat gerçek trafik topla.
- PostgreSQL'de log_min_duration_statement aynı işi yapar. pg_stat_statements eklentisi ise sorguları toplam süreye göre sıralar.
- Kayıtları elle okumak yerine gruplayarak özetle. "Tek seferde 3 saniye" kadar önemli olan bir diğer şey: "20 ms ama dakikada 5.000 kez".
- Uygulama tarafında ORM'in ürettiği ham SQL'i logla. Beklemediğin sorguları orada görürsün.
Bu ölçüm alışkanlığı tarayıcı tarafındaki profil çıkarma mantığıyla aynıdır; JavaScript performans notlarında da önce ölç, sonra dokun kuralı geçerli.
EXPLAIN çıktısını okumayı öğren
Sorgunun önüne EXPLAIN yazınca veritabanının planını görürsün. EXPLAIN ANALYZE ise sorguyu gerçekten çalıştırıp ölçer. Şunlara bak:
| Gördüğün şey | Anlamı | Yapılacak |
|---|---|---|
| Full table scan / Seq Scan | Tüm tablo satır satır okunuyor | WHERE kolonuna index düşün |
| Beklenen satır ≫ dönen satır | Gereksiz satır okunuyor | Filtreyi daraltmak veya daha iyi index |
| Filesort / Sort | Sıralama bellekte/diskte yapılıyor | ORDER BY kolonunu index'e ekle |
| Nested loop + büyük tablo | JOIN her satır için tekrar arıyor | JOIN kolonunda index olmalı |
| Tahmin ile gerçek satır çok farklı | İstatistikler eski | ANALYZE / tablo istatistiğini yenile |
Gerçek boyutta veriyle test et
- 500 satırlık geliştirme veritabanında her sorgu hızlıdır. Test verini üret: basit bir döngüyle yüz binlerce satır ekle.
- Veri üretimini tekrarlanabilir hale getirmek için küçük bir kabuk betiği yaz. Bash script rehberindeki döngü ve parametre kalıpları burada işe yarar.
- Ölçümü ısıtılmış cache ile ve soğuk cache ile ayrı ayrı yap. İkisi arasındaki fark diske ne kadar bağımlı olduğunu gösterir.
- Deneme ortamını Docker ile ayağa kaldırmak, üretim verisini kirletmeden aynı sürümü test etmeni sağlar.
2. Index Kur, Sorguyu Yeniden Yaz
Elinde suçlu sorgu ve planı varken düzeltme kısmı şaşırtıcı derecede mekanik hale gelir.
Doğru index'i, doğru sırayla
- WHERE, JOIN ve ORDER BY'da geçen kolonları listele.
- Eşitlik filtrelerini başa, aralık filtrelerini (>, <, BETWEEN) sona koy. Bileşik index'te sıra her şeydir.
- (kullanici_id, olusturma_tarihi) index'i, tek başına kullanici_id aramasında da çalışır. Tersi çalışmaz. Yani soldan başlayan önek kuralını unutma.
- Sorgunun ihtiyaç duyduğu tüm kolonlar index'te varsa veritabanı tabloya hiç gitmez. Buna kapsayan (covering) index denir; en büyük kazançlar buradan gelir.
- Her kolona index atma. Her index yazma işlemini yavaşlatır ve disk yer. Kullanılmayan index'leri düzenli olarak tespit edip sil.
Index'i işe yaramaz hale getiren yazımlar
- Kolonu fonksiyona sokma: WHERE YEAR(tarih) = 2024 index'i baypas eder. Aralık kullan: WHERE tarih >= '2024-01-01' AND tarih < '2025-01-01'.
- Baştan joker: LIKE '%kelime%' index kullanamaz. Metin araması gerekiyorsa tam metin index'ine geç.
- Tip uyuşmazlığı: sayısal kolonu string ile karşılaştırmak sessizce dönüşüm yapar ve index'i devre dışı bırakır.
- OR yığını: çok kollu OR yerine UNION ALL ya da IN denemesi genelde daha iyi plan üretir.
- SELECT *: ihtiyacın olmayan kolonlar covering index şansını yok eder, ağ trafiğini de şişirir.
JOIN, sayfalama ve N+1
- JOIN'de her iki taraftaki eşleşme kolonu index'li ve aynı tipte
© 2026 Yazılım Atölyesi