İndekslenmemiş Bir Sütun Veritabanımızı Nasıl Çökertti
Tek bir eksik indeks, 8 ms'lik bir API'yi 8 saniyelik bir kabusa dönüştürdü.
Büyük bir sürüm öncesinde yük testi gerçekleştirdik. Yerel geliştirme ortamında 100 kayıtla her şey yolundaydı. Ardından, üretim boyutundaki verilerle 1,5 milyon satır üzerinde 500 kullanıcıyı simüle ettik.
Sonuçlar kötüydü:
- API yanıt süreleri 45 ms'den 8.000 ms'ye fırladı.
- Veritabanı CPU kullanımı %100'e ulaştı.
- Bağlantı havuzları tükendi ve zaman aşımı (timeout) hatalarına yol açtı.
Yavaş sorgu günlüğünü (slow-query log) kontrol ettik ve kullanıcı kimliği (user ID) ile duruma (status) göre sipariş geçmişini getiren bir uç nokta (endpoint) bulduk.
PostgreSQL üzerinde EXPLAIN ANALYZE çalıştırmak bir Sequential Scan (Ardışık Tarama) gösterdi. user_id üzerinde bir indeks olmadığı için motor, her istek için 1,5 milyon satırın tamamını okuyordu.
100 eşzamanlı istek ile tek seferde 150 milyon satır tarandı.
Çözüm sadece beş dakika sürdü.
user_id üzerinde basit bir indeks oluşturmak yerine, (user_id, status, created_at DESC) üzerinde bir bileşik (composite) indeks oluşturduk. Bu sayede veritabanı şunları yapabildi:
user_idile filtreleme.statusile filtreleme.- En yeni satırları anında döndürme.
- Ekstra sıralama adımlarını atlama.
İşlem sırasında tablonun kilitlenmemesi için CREATE INDEX CONCURRENTLY kullandık.
Çözümden sonra:
- Sorgu süresi 8.150 ms'den 0,14 ms'ye düştü.
- API gecikmesi (latency) 8 saniyeden 12 ms'ye geriledi.
- CPU kullanımı %100'den %8'in altına indi.
Alınan dersler:
- Yerel testler yanıltıcı olabilir; 100 satır, bir milyonu temsil etmez.
- Yabancı anahtarlarınızı (foreign keys) indeksleyin; çoğu ORM bunu atlar.
- Daha fazla donanım satın almadan önce
EXPLAIN ANALYZEçalıştırın. - İndeksleri, gerçekten çalıştırdığınız sorgulara göre tasarlayın.
Önce sunucuları ölçeklendirmeyin. Sorguları ölçeklendirin.
