Veritabanı Optimizasyonu: SQL Performansı ve İndeksleme
Veritabanı performansı, uygulama hızını doğrudan etkiler. Bu rehberde SQL sorgu optimizasyonu, indeksleme stratejileri ve veritabanı performans ipuçlarını anlatıyoruz.
Son güncelleme:Veritabanı Performansı Neden Önemlidir?
Yavaş veritabanı sorguları, uygulama yanıt süresini artırır. 100ms'den uzun sorgular, kullanıcı deneyimini olumsuz etkiler.
Veritabanı darboğazı (bottleneck), uygulama performansının %80'ini etkileyebilir. CPU veya bellek yerine veritabanı genellikle en büyük darboğazdır.
Optimizasyon, donanım maliyetlerini azaltır. Daha verimli sorgular, daha az sunucu kaynağı gerektirir.
İndeksleme Stratejileri
B-Tree indeks: En yaygın indeks türü. Eşitlik (=) ve aralık (<, >, BETWEEN) sorgularında etkilidir. Primary key ve foreign key'ler otomatik olarak indekslenir.
Composite indeks: Birden fazla sütunu içeren indeks. Sorgu sırasına göre sütun sırasını belirleyin. WHERE clause'daki ilk sütun en seçici olmalıdır.
Covering indeks: Sorguda kullanılan tüm sütunları içeren indeks. Tablo erişimi gerekmez, sadece indeks okunur.
Partial indeks: Belirli koşulu sağlayan satırlar için indeks. WHERE is_active = true gibi. İndeks boyutunu azaltır.
İndeks bakım: Kullanılmayan indeksleri kaldırın. Her indeks, INSERT/UPDATE/DELETE işlemlerini yavaşlatır. EXPLAIN ile indeks kullanımını kontrol edin.
Sorgu Optimizasyonu
EXPLAIN / EXPLAIN ANALYZE: Sorgu yürütme planını analiz edin. Seq Scan (tam tablo taraması) yerine Index Scan (indeks taraması) hedefleyin.
N+1 problemi: İlişkili verileri tek sorguda alın (JOIN) yerine her kayıt için ayrı sorgu yapmayın. ORM'lerde eager loading kullanın.
SELECT * kullanmayın: Sadece gerekli sütunları seçin. Bu, ağ trafiğini ve bellek kullanımını azaltır.
JOIN optimizasyonu: Gereksiz JOIN'lerden kaçının. Küçük tabloları önce JOIN edin. LEFT JOIN yerine INNER JOIN kullanın (mümkünse).
Subquery vs JOIN: Correlated subquery'ler yavaştır. Mümkün olduğunda JOIN veya CTE (Common Table Expression) kullanın.
Caching ve Connection Pooling
Query cache: Sık kullanılan sorgu sonuçlarını önbellekleyin. Redis veya Memcached ile application-level caching yapın.
Connection pooling: Veritabanı bağlantılarını yeniden kullanın. Her istekte yeni bağlantı açmak pahalıdır. pgBouncer (PostgreSQL) veya HikariCP (Java) kullanın.
Read replicas: Okuma işlemlerini replica sunuculara yönlendirin. Write işlemlerini primary sunucuda tutun. Bu, okuma yükünü dağıtır.
Materialized views: Karmaşık aggregation sorguları için materialized view oluşturun. Periyodik olarak yenileyin.
Veritabanı Tasarımı
Normalizasyon: Veri tekrarını azaltın (1NF, 2NF, 3NF). Ancak aşırı normalizasyon, JOIN sayısını artırır ve performansı düşürür.
Denormalizasyon: Okuma ağırlıklı sistemlerde (analytics, reporting) denormalizasyon performansı artırır. Trade-off: veri tutarlılığı vs performans.
Partitioning: Büyük tabloları (milyonlarca satır) partition'lara bölün. Range partitioning (tarih bazlı) en yaygın yöntemdir.
Data types: Doğru veri tiplerini kullanın. VARCHAR yerine INT, TEXT yerine VARCHAR (uygun boyutta). Küçük veri tipleri daha az yer kaplar ve daha hızlı işlenir.
İzleme ve Profilleme
Slow query log: Yavaş sorguları loglayın. PostgreSQL: log_min_duration_statement = 100. MySQL: slow_query_log = 1.
Performance Schema (MySQL) / pg_stat_statements (PostgreSQL): Sorgu istatistiklerini toplayın. En çok zaman alan sorguları tespit edin.
APM araçları: Datadog, New Relic veya Dynatrace ile veritabanı performansını izleyin. Sorgu sürelerini ve hata oranlarını takip edin.
Index usage: pg_stat_user_indexes (PostgreSQL) ile indeks kullanımını kontrol edin. Kullanılmayan indeksleri kaldırın.