Rehberler Uzun Okuma Django

Django sorgulariniz yavas mi?

QuerySet lazy evaluation, join stratejileri ve profilleme araclari.

29 Ocak 2026 22 dk okuma
Paylaş
X in

Giris

Django ORM, SQL yazmadan veritabani islemleri yapmanizi saglar ancak yanlis kullanildiginda her istekte yuzlerce gereksiz sorgu uretebilir. QuerySet'ler lazy'dir: degerlendirilene kadar SQL calismaz. Bu gecikme guclu bir ozelliktir ama dongu icinde iliskili nesnelere erisim N+1 problemini dogurur.

Bu rehberde QuerySet optimizasyon tekniklerini, Django Debug Toolbar ve connection.queries ile profillemeyi ve buyuk tablolarda guvenli sayfalama stratejilerini ele aliyoruz.

QuerySet Temelleri ve Lazy Evaluation

Post.objects.filter(status='published') henuz SQL uretmez. list(), len(), iterate veya slice islemleri sorguyu tetikler. queryset.count() icin ayri bir COUNT sorgusu calisir; bu yuzden len(queryset) yerine count() tercih edilmelidir.

  • all(), filter(), exclude(), order_by() yeni QuerySet doner
  • values() ve values_list() dict/tuple sonuc
  • exists() ve count() optimize edilmis sorgular
qs = Post.objects.filter(status='published')  # SQL yok
for post in qs:
    print(post.title)  # Tek SELECT

# Kotu: her post icin ayri sorgu
for post in Post.objects.all():
    print(post.author.username)  # N+1!

N+1 Problemi ve Tespiti

N+1: 1 sorgu ana kayitlari getirir, N sorgu her satir icin iliskili veriyi ceker. 100 blog yazisi listesinde yazar adi gosterirken 101 sorgu olusabilir. django-debug-toolbar veya logging ile connection.queries uzunlugunu izleyin.

# Kotu
posts = Post.objects.all()
for p in posts:
    print(p.author.email)  # Her iterasyonda SELECT

# Iyi
posts = Post.objects.select_related('author')
for p in posts:
    print(p.author.email)  # Tek JOIN
Template icinde {{ post.author.name }} kullaniyorsaniz view'da select_related planlayin.

select_related: ForeignKey ve OneToOne

select_related SQL JOIN kullanir; ForeignKey ve OneToOne iliskilerde tek sorguda veriyi getirir. Zincirleme iliskiler icin cift alt cizgi kullanilir: select_related('author__profile').

Post.objects.select_related(
    'author',
    'category',
).filter(status='published')

# CBV'de
class PostDetailView(DetailView):
    queryset = Post.objects.select_related('author', 'category')

prefetch_related: ManyToMany ve Ters FK

prefetch_related ayri sorgularla veriyi bellege alir ve Python tarafinda eslestirir. ManyToMany ve reverse ForeignKey icin uygundur. Prefetch() nesnesi ile alt QuerySet filtrelenebilir.

  • select_related: JOIN, tek sorgu
  • prefetch_related: ayri sorgular + bellek eslestirme
  • Her ikisi birlikte kullanilabilir
from django.db.models import Prefetch

Post.objects.prefetch_related(
    'tags',
    Prefetch(
        'comments',
        queryset=Comment.objects.filter(is_approved=True),
    ),
)

only, defer ve annotate

only() ve defer() belirli alanlari yukler veya haric tutar; buyuk TEXT/BLOB kolonlarda bant genisligi tasarrufu saglar. annotate() ve aggregate() SQL seviyesinde hesaplama yapar; Python dongusunden kacinir.

from django.db.models import Count, Avg

Post.objects.annotate(
    comment_count=Count('comments'),
    avg_rating=Avg('comments__rating'),
).filter(comment_count__gte=5)

Post.objects.only('id', 'title', 'slug').defer('body')

Profilleme ve Uretim Ipuclari

Gelistirmede django-debug-toolbar SQL panelini kullanin. Uretimde Sentry veya APM ile yavas endpoint'leri izleyin. iterator(chunk_size=2000) buyuk export islerinde bellek tuketimini dusurur.

  1. View'da gereken iliskileri onceden yukle
  2. Pagination ile LIMIT/OFFSET kullan
  3. Indeksleri migration'da tanimla
  4. Raw SQL yalnizca olculmus darbogazlarda
for row in Post.objects.iterator(chunk_size=500):
    export_row(row)

Sonuc

ORM kolayligi performans maliyeti getirmez; dogru QuerySet zinciri ile hem okunabilir hem hizli kod yazilir. Her optimizasyonu olcmeden uygulamayin; bazen ekstra JOIN yerine cache daha uygun olabilir.

  • select_related/prefetch_related'i template ihtiyacina gore secin
  • exists() bos kontrol icin count()'tan hizli
  • bulk_create ve bulk_update toplu islemlerde kullanin