دوره‌ها / Django / select_related و prefetch_related (Performance)

select_related و prefetch_related (Performance)

15 دقیقه Article

بهینه‌سازی Query: جلوگیری از N+1 Problem ⚡

وقتی از ForeignKey یا ManyToMany استفاده می‌کنید، ممکنه مشکل N+1 Query پیش بیاد. یعنی برای هر شیء یک Query جداگانه اجرا بشه. select_related و prefetch_related این مشکل رو حل می‌کنن!

مشکل N+1

# ❌ بد - N+1 Query Problem
posts = Post.objects.all()
for post in posts:
    print(post.author.username)  # برای هر پست یک Query جدید!

# ✅ خوب - فقط 2 Query
posts = Post.objects.select_related('author')
for post in posts:
    print(post.author.username)  # همه داده‌ها از قبل لود شدن!

select_related: برای ForeignKey

select_related برای روابط ForeignKey و OneToOne استفاده میشه. با یک JOIN در SQL همه داده‌ها رو یکجا می‌گیره:

from blog.models import Post

# لود کردن author برای همه پست‌ها در یک Query
posts = Post.objects.select_related('author')

# برای چند ForeignKey
posts = Post.objects.select_related('author', 'category')

# استفاده در فیلتر
posts = Post.objects.filter(published=True).select_related('author')

prefetch_related: برای ManyToMany و Reverse ForeignKey

prefetch_related برای روابط ManyToMany و Reverse ForeignKey استفاده میشه:

from blog.models import Post, Tag

# لود کردن تگ‌های همه پست‌ها
posts = Post.objects.prefetch_related('tags')

# لود کردن کامنت‌های همه پست‌ها
posts = Post.objects.prefetch_related('comment_set')

# ترکیب با select_related
posts = Post.objects.select_related('author').prefetch_related('tags', 'comment_set')
قانون طلایی:
  • select_related برای ForeignKey و OneToOne
  • prefetch_related برای ManyToMany و Reverse ForeignKey
  • ✅ همیشه وقتی از relation استفاده می‌کنید، این‌ها رو اضافه کنید!

مثال عملی

# blog/views.py
def post_list(request):
    # بهینه شده - فقط 3 Query به جای 100+ Query!
    posts = Post.objects.select_related(
        'author', 'category'
    ).prefetch_related(
        'tags', 'comment_set'
    ).filter(published=True)
    
    return render(request, 'blog/list.html', {'posts': posts})

آماده رفتن به درس بعدی هستید؟

این درس را به پایان رساندید و می‌توانید به درس بعدی بروید.

برای ذخیره پیشرفت وارد شوید