Django ORM Optimizasyonu: select_related vs prefetch_related
Django'da N+1 sorgu felaketini önleyen iki can simidi.
select_related: Tek bir kargo kamyonuna birbiriyle doğrudan bağlı kutuları yüklemektir (SQL JOIN). prefetch_related: Farklı adalardaki malları ayrı kargo uçaklarıyla getirip masada birleştirmektir (IN sorgusu).
select_related, ForeignKey ve OneToOne ilişkilerde tek bir SQL INNER/LEFT JOIN atarak veriyi birleştirir. prefetch_related ise ManyToMany veya ters ForeignKey ilişkilerinde her ilişki için ayrı bir "WHERE id IN (...)" sorgusu atar ve Python tarafında birleştirir.
“Bire-bir ve bire-çok ilişkilerde tek JOIN ile çekmek için select_related(); çoğa-çok veya ters ilişkilerde kartezyen çarpımdan kaçınmak için prefetch_related() kullanılır. İkisi de döngü içindeki N+1 sorgu problemini engeller.”
# KÖTÜ: 100 yazar için 101 sorgu!
books = Book.objects.all()
# DOĞRU (ForeignKey): Tek SQL JOIN
books = Book.objects.select_related('author').all()
# DOĞRU (ManyToMany): 2 optimize SQL sorgusu
books = Book.objects.prefetch_related('categories').all()
ManyToMany ilişkilerinde select_related() kullanmaya çalışmak (Django izin vermez, hata fırlatır).