Skip to main content
Veritabanı

SQL Sorgu Optimizasyonu: Veritabanı Performansını Artırmanın Kapsamlı Rehberi

Mart 29, 2026 6 dk okuma 2 views Raw
SQL sorgu optimizasyonu ve veritabanı performansı
İçindekiler

SQL Sorgu Optimizasyonu Neden Önemlidir?

Modern uygulamaların büyük çoğunluğu ilişkisel veritabanlarına dayanır ve bu veritabanlarıyla iletişim SQL sorguları aracılığıyla gerçekleşir. Uygulamanızın performansı doğrudan SQL sorgularınızın verimliliğiyle ilişkilidir. Kötü yazılmış bir sorgu, milyonlarca satırlık bir tabloda saniyeler hatta dakikalar sürebilirken, optimize edilmiş aynı sorgu milisaniyeler içinde tamamlanabilir.

Veritabanı performans sorunları genellikle uygulamanın büyümesiyle ortaya çıkar. Başlangıçta birkaç bin satırla sorunsuz çalışan sorgular, veri hacmi arttığında ciddi performans darboğazlarına neden olabilir. Bu nedenle sorgu optimizasyonunu erken aşamada öğrenmek ve uygulamak kritik öneme sahiptir.

Sorgu Planlarını Anlamak: EXPLAIN Komutu

SQL optimizasyonunun ilk adımı, veritabanı motorunun sorgunuzu nasıl çalıştırdığını anlamaktır. Bunun için EXPLAIN komutu kullanılır. EXPLAIN, sorgunuzun yürütme planını gösterir ve hangi indekslerin kullanıldığını, tablolar arası birleştirme yöntemlerini ve tahmini satır sayılarını ortaya koyar.

EXPLAIN Çıktısını Okumak

EXPLAIN çıktısında dikkat edilmesi gereken temel alanlar şunlardır:

  • type: Tablo erişim türünü belirtir. En iyiden en kötüye: system > const > eq_ref > ref > range > index > ALL
  • possible_keys: Sorgu için kullanılabilecek potansiyel indeksleri listeler
  • key: Gerçekte kullanılan indeksi gösterir
  • rows: Tahmini olarak taranacak satır sayısını belirtir
  • Extra: Ek bilgiler sağlar; "Using filesort" veya "Using temporary" uyarı işaretleridir

EXPLAIN ANALYZE ile Gerçek Performans Ölçümü

PostgreSQL ve MySQL 8.0+ sürümlerinde EXPLAIN ANALYZE komutu, sorguyu gerçekten çalıştırarak fiili yürütme sürelerini gösterir. Bu, tahmini ve gerçek değerler arasındaki farkları tespit etmek için son derece değerlidir.

Optimizasyon çalışmasına başlamadan önce her zaman EXPLAIN ile mevcut durumu analiz edin. Ölçemediğiniz şeyi iyileştiremezsiniz.

İndeksleme Stratejileri

İndeksler, veritabanı performansının temel yapı taşlarıdır. Doğru indeksleme, sorgu performansını dramatik şekilde artırabilir. Ancak gereksiz veya yanlış indeksler hem disk alanı israfına hem de yazma işlemlerinde yavaşlamaya neden olabilir.

B-Tree İndeksleri

B-Tree indeksleri en yaygın kullanılan indeks türüdür ve çoğu veritabanı motorunda varsayılan olarak kullanılır. Eşitlik karşılaştırmaları, aralık sorguları ve sıralama işlemleri için idealdir.

Bileşik İndeksler

Birden fazla sütunu kapsayan bileşik indeksler, çok sütunlu WHERE koşulları ve ORDER BY ifadeleri için kritiktir. Bileşik indeks oluştururken sütun sıralaması büyük önem taşır:

  1. En çok filtreleme yapılan sütunları başa koyun
  2. Eşitlik karşılaştırması yapılan sütunlar, aralık sorgularından önce gelmelidir
  3. ORDER BY sütunlarını en sona ekleyin

Kaplama İndeksleri (Covering Index)

Kaplama indeksi, sorgunun ihtiyaç duyduğu tüm sütunları içeren bir indekstir. Bu durumda veritabanı motoru tabloya gitmeden sadece indeksten veri okur, bu da performansı önemli ölçüde artırır. EXPLAIN çıktısında "Using index" ifadesi bu durumu belirtir.

Kısmi İndeksler (Partial Index)

PostgreSQL gibi veritabanlarında kısmi indeksler oluşturabilirsiniz. Bu indeksler yalnızca belirli bir koşulu sağlayan satırlar için oluşturulur ve hem disk kullanımını azaltır hem de indeks bakım maliyetini düşürür.

İndeks TürüKullanım AlanıAvantajDezavantaj
B-TreeGenel amaçlıÇok yönlüBüyük veri setlerinde alan kullanımı
HashEşitlik sorgularıÇok hızlı eşitlik aramasıAralık sorguları desteklemez
GINTam metin arama, JSONBKarmaşık veri türleriYavaş güncelleme
GiSTCoğrafi veri, aralık türleriYakınlık aramalarıB-Tree kadar hızlı değil

JOIN Optimizasyonu

JOIN işlemleri veritabanı sorgularının en maliyetli kısımlarından biridir. Veritabanı motorları farklı JOIN algoritmaları kullanır ve her birinin farklı senaryolarda avantajları vardır.

Nested Loop Join

Küçük veri setleri ve indeksli birleştirmeler için en uygun yöntemdir. Dış tablodaki her satır için iç tabloda arama yapar. İç tabloda indeks varsa çok verimlidir.

Hash Join

Büyük tablolar arasındaki eşitlik birleştirmeleri için idealdir. Küçük tablodan bir hash tablosu oluşturur ve büyük tabloyu tarayarak eşleşmeleri bulur. İndeks gerektirmez ancak bellek kullanımı yüksek olabilir.

Merge Join

Her iki tablo da birleştirme anahtarına göre sıralıysa en verimli yöntemdir. Sıralı verileri paralel olarak tarar ve eşleşmeleri bulur.

JOIN Optimizasyonu İçin İpuçları

  • JOIN koşullarındaki sütunlara mutlaka indeks ekleyin
  • Gereksiz JOIN ifadelerinden kaçının; sadece ihtiyaç duyulan tabloları birleştirin
  • Alt sorgular yerine JOIN kullanmayı tercih edin, ancak duruma göre değerlendirin
  • JOIN sırasını veritabanı motoruna bırakın; optimizer genellikle en iyi sırayı bulur
  • Büyük tablolarda INNER JOIN, LEFT JOIN'den daha performanslıdır çünkü daha fazla filtreleme imkanı sunar

N+1 Problemi ve Çözümleri

N+1 problemi, özellikle ORM kullanan uygulamalarda sıkça karşılaşılan bir performans sorunudur. Ana sorgu bir kayıt listesi getirirken, her kayıt için ayrı bir sorgu daha çalıştırılmasıyla ortaya çıkar.

N+1 Probleminin Anatomisi

Bir blog uygulamasında yazıları ve yazarlarını listelerken tipik N+1 senaryosu şöyledir: İlk sorgu tüm yazıları getirir (1 sorgu), ardından her yazının yazarı için ayrı bir sorgu çalışır (N sorgu). 100 yazı varsa toplamda 101 sorgu çalışır.

Çözüm Yöntemleri

  • Eager Loading: ORM'de ilişkili verileri ana sorguyla birlikte yükleyin. Entity Framework'te Include(), Django'da select_related() kullanın
  • Batch Loading: İlişkili verileri gruplar halinde yükleyin. Hibernate'te @BatchSize anotasyonu kullanılabilir
  • JOIN Fetch: İlişkili verileri tek bir JOIN sorgusuyla getirin
  • DataLoader Pattern: GraphQL uygulamalarında yaygın olan bu desen, istekleri toplar ve tek bir sorguda çalıştırır

Sorgu Önbellekleme Stratejileri

Veritabanı sorgularını optimize etmenin ötesinde, sık kullanılan sorgu sonuçlarını önbelleğe almak performansı dramatik şekilde artırabilir.

Uygulama Düzeyinde Önbellekleme

Redis veya Memcached gibi bellek içi veri depoları kullanarak sorgu sonuçlarını önbelleğe alabilirsiniz. Bu yaklaşım özellikle okuma ağırlıklı uygulamalarda büyük fayda sağlar.

Veritabanı Düzeyinde Önbellekleme

MySQL'in Query Cache özelliği (8.0'da kaldırıldı), PostgreSQL'in paylaşımlı tampon havuzu ve materialized view'lar veritabanı düzeyinde önbellekleme sağlar.

Önbellekleme İçin En İyi Uygulamalar

  1. Sık okunan ve nadiren değişen verileri önbelleğe alın
  2. Önbellek geçersizleme stratejinizi önceden planlayın
  3. TTL (Time to Live) değerlerini veri güncelleme sıklığına göre ayarlayın
  4. Cache stampede problemine karşı önlem alın
  5. Önbellek isabet oranlarını izleyin ve optimize edin

İleri Düzey Optimizasyon Teknikleri

Tablo Bölümleme (Partitioning)

Büyük tabloları mantıksal bölümlere ayırmak, sorgu performansını önemli ölçüde artırabilir. Tarih bazlı bölümleme, zaman serisi verileri için özellikle etkilidir. Veritabanı motoru yalnızca ilgili bölümleri tarar, bu da büyük tablolarda dramatik performans iyileştirmesi sağlar.

Sorgu Yeniden Yazma

Bazen aynı sonucu veren farklı sorgu yapıları arasında büyük performans farkları olabilir. Alt sorguları JOIN'lere dönüştürmek, EXISTS kullanmak veya pencere fonksiyonları ile denormalize hesaplamalar yapmak sorgu performansını artırabilir.

Bağlantı Havuzu Yönetimi

Veritabanı bağlantıları oluşturmak maliyetli bir işlemdir. PgBouncer, HikariCP veya uygulamanızın yerleşik bağlantı havuzu mekanizmalarını kullanarak bağlantı yönetimini optimize edin.

Performans İzleme ve Sürekli Optimizasyon

SQL optimizasyonu tek seferlik bir iş değildir. Veri hacmi ve kullanım kalıpları değiştikçe sorgularınızın performansı da değişir. Sürekli izleme ve optimizasyon döngüsü oluşturun:

  • Yavaş sorgu günlüklerini (slow query log) aktif edin ve düzenli olarak inceleyin
  • APM araçlarıyla sorgu performansını izleyin
  • İndeks kullanım istatistiklerini periyodik olarak gözden geçirin
  • Kullanılmayan indeksleri temizleyin
  • Veritabanı sürüm güncellemelerini takip edin; yeni sürümler genellikle optimizer iyileştirmeleri içerir

En iyi optimizasyon, hiç çalıştırılmayan sorgudur. Gerçekten ihtiyaç duyulmayan verileri sorgulamaktan kaçının ve uygulamanızın veri erişim kalıplarını düzenli olarak gözden geçirin.

Sonuç

SQL sorgu optimizasyonu, modern yazılım geliştirmenin temel yetkinliklerinden biridir. EXPLAIN planlarını okumayı, doğru indeksleme stratejilerini uygulamayı, JOIN performansını artırmayı, N+1 problemini çözmeyi ve etkili önbellekleme stratejileri geliştirmeyi öğrenmek, uygulamalarınızın performansını katlanarak artıracaktır. Unutmayın, optimizasyon sürekli bir süreçtir; düzenli izleme ve iyileştirme ile veritabanınızın her zaman en iyi performansı sunmasını sağlayabilirsiniz.

Bu yazıyı paylaş