Laravel'de N+1 Sorgularını Avlamak ve Gereksiz Sorguları Yok Etmek
Performans çalışmaları genellikle sıkıcıdır.
Her zaman gecikmeyi %80 oranında azalttığınız kahramanlık hikayeleriyle ilgili değildir. Çoğu gün, temizlik yapmakla ilgilidir. Çalıştırdığınızdan haberdar olmadığınız sorgular bulursunuz. Sonra da onları silersiniz.
Eğer Laravel uygulamanız büyüyorsa, muhtemelen şu üç sorunla karşılaşıyorsunuzdur.
1. Gizli N+1 Sorguları
Göremediğiniz şeyi düzeltemezsiniz. Yerel ortamınızda beyondcode/laravel-query-detector gibi bir araç kullanın. Bu araç, döngü ve tembel yükleme (loop-and-lazy-load) desenini kullandığınızda sizi uyarır.
Bunu production ortamında çalıştırmayın. Ek yük (overhead) getirir. Yalnızca uygulamanız local veya testing modundayken kaydedin.
2. Eager Loading İsrafı
İnsanlar N+1 sorunlarını genellikle with() ekleyerek çözerler. Ancak bu yeni bir sorun yaratır. Görünümünüzün (view) artık kullanmadığı bir ilişkiyi eager-load ile yüklüyor olabilirsiniz.
Eğer bir yeniden tasarım bir tablodan bir sütunu kaldırırsa, controller'ınızdaki ilgili with() çağrısını da kaldırmalısınız. Çöpe attığınız veri için ödeme yapıyorsunuz.
Her eager load işlemini bir talep (claim) olarak görün. Eğer veriyi kullanmıyorsanız, o talebi kaldırın.
3. Aynı Veriyi Tekrar Hesaplamak
Bazı değerler tüm istek (request) boyunca aynı kalır. Eğer bunları birden fazla kez hesaplarsanız, CPU israf edersiniz. Bunu düzeltmek için memoization kullanın.
Örnek:
protected ?string $defaultConnection = null;
public function getDefaultConnectionName(): string
{
return $this->defaultConnection ??= $this->resolveDefaultConnection();
}
??= operatörü değeri bir kez hesaplar ve isteğin geri kalanı için yeniden kullanır.
4. Dashboard Sorgu Tuzakları
Dashboard'lar genellikle her bir kart için ayrı bir count() sorgusu çalıştırır. Altı kartınız varsa, altı sorgu çalıştırırsınız.
Bunun yerine şu iki şeyi yapın:
- Sayılarınızı gruplandırın. Tek bir tablo için tüm toplamları tek bir sorguda alın.
- Kısa süreli bir cache kullanın. Dashboard istatistiklerinin saniyelik olarak güncel olması gerekmez. Onları beş dakikalığına cache'leyin.
Bir ziyaretçi sorgunun maliyetini öder. Diğer herkes önbelleğe alınmış (cached) sonucu alır.
Son İpucu: Regresyonları Önleyin
Eğer geliştiriciler daha sonra kötü kodu tekrar eklerlerse, temizlik çalışmaları başarısız olur. Sorgu sayılarınızı doğrulamak (assert) için Pest kullanın. Bir sayfanın çalıştırabileceği sorgu sayısı için bir üst sınır belirleyin. Eğer bir geliştirici N+1 eklerse, test başarısız olacaktır.
Optimizasyon çoğunlukla kaldırmakla ilgilidir. Kullanılmayan yüklemeleri kaldırın. Tekrar hesaplanan değerleri kaldırın. Gereksiz sorguları kaldırın.
