Veritabanı İndeksleme ve Sorgu Optimizasyonu Rehberi: Yanıt Sürelerini Azaltma
Yavaş SQL sorgularını tespit etme, doğru indeks tipi seçme ve veritabanı yanıt sürelerini milisaniyelere düşürme adımları. Modern web sistemleri için performans rehberi.
Sistem Yöneticisi
Kıdemli Yazılım Mimarı
Giriş: Neden Sorgu Optimizasyonu?
Modern web uygulamalarında yavaşlık sebebi genelde sunucu CPU değil, kötü SQL sorguları. Dijital ajans projelerinde veritabanı darboğazı sayfa açılışını bozar. Çözüm: Doğru indeksleme ve sorgu refactor.
Adım 1: Yavaş Sorguları Tespit Et
Önce ölçüm. Ezbere optimizasyon yok. Slow query log aktif et.
- PostgreSQL:
pg_stat_statementseklentisi kur.mean_exec_timeyüksek sorguları bul. - MySQL:
slow_query_log = 1velong_query_time = 0.5ayarla.
Adım 2: EXPLAIN ve EXPLAIN ANALYZE ile Yürütme Planını Oku
Sorgu motorunun ne yaptığını gör. EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'test@example.com'; çalıştır.
- Sequential Scan / Table Scan: Kötü. Tüm disk taranır. İndeks yok demek.
- Index Scan / Index Only Scan: İyi. Doğrudan indeks ağacından veri çeker.
- Cost ve Actual Time: Maliyet yüksekse indeks stratejisini değiştir.
Adım 3: Doğru İndeks Tipini Uygula
Her kolona indeks atma. Yazma (INSERT/UPDATE) maliyeti artar. Amaca uygun indeks seç.
B-Tree İndeks (Standart)
Eşitlik (=) ve aralık (>, <, BETWEEN) sorguları için varsayılan tip.
CREATE INDEX idx_orders_created_at ON orders(created_at);
Bileşik (Composite) İndeks
Birden fazla kolonla filtreleme varsa tek indeks yap. Kolon sırası kritik: En seçici (high cardinality) kolon başta olmalı.
CREATE INDEX idx_users_status_created ON users(status, created_at);
Kısmi (Partial) İndeks
Tablonun sadece küçük bir kısmını sorguluyorsan tüm tabloyu indeksleme. Disk ve RAM tasarrufu sağlar.
CREATE INDEX idx_active_users ON users(id) WHERE status = 'active';
Adım 4: Sorgu Yazım Hatalarını Düzelt
İndeks olsa bile sorgu yanlış yazılırsa veritabanı indeksi görmezden gelir.
- İndeksli kolonda fonksiyon kullanma:
WHERE DATE(created_at) = '2023-01-01'indeksi bozar. Yerine:WHERE created_at >= '2023-01-01 00:00:00' AND created_at < '2023-01-02 00:00:00'. - SELECT * yapma: Yalnızca gereken kolonları çek.
Index Only Scanşansını yok etme. Network ve bellek yükünü azalt. - N+1 sorgu probleminden kaçın: Döngü içinde sorgu atma. JOIN veya
WHERE id IN (...)kullan. - Leading Wildcard LIKE yapma:
LIKE '%abc'B-Tree indeksi kullanamaz. Full text search veya Trigram (pg_trgm) indeks kullan.
İpucu: Modern web trendleri gereği mikroservis mimarilerinde bağlantı havuzu (Connection Pooler örn. PgBouncer) kullanmak, sorgu süresi kadar bağlantı açma maliyetini de optimize eder.
Adım 5: İndeks Bakımı ve Temizliği
Kullanılmayan indeksler sisteme safi yük. Periyodik olarak kontrol et ve sil.
- PostgreSQL kullanılmayan indeks tespiti:
SELECT * FROM pg_stat_user_indexes WHERE idx_scan = 0; - Gereksiz indeksi sil:
DROP INDEX CONCURRENTLY idx_name;(Tabloyu kilitlememek için CONCURRENTLY kullan).