Yükleniyor...

Django Performans Optimizasyonu: 10 Kanıtlanmış Teknik [2026 Rehberi]

Yazar: Burak Balkı | Kategori: Testing | Okuma Süresi: 35 dk

Bu kapsamlı rehber, 2026'nın en güncel Django performans optimizasyon tekniklerini, pratik kod örnekleriyle ve adım adım süreçlerle ele alıyor. Veritabanı so...

# Django Performans Optimizasyonu: 10 Kanıtlanmış Teknik [2026 Rehberi] Web uygulamaları dünyasında hız, kullanıcı memnuniyeti ve SEO için vazgeçilmez bir faktördür. Kullanıcılar, 2026 itibarıyla milisaniyelerle ifade edilen gecikmelere bile tahammül göstermiyor. Peki, Python ve Django'nun gücünü kullanan uygulamalarınızın bu beklentiyi karşıladığından emin misiniz? Son projemizde, yavaş çalışan bir Django API'ını optimize ederek yükleme sürelerini %50'den fazla azalttığımızda, doğru stratejilerin ne kadar kritik olduğunu bir kez daha deneyimledim. Bu kapsamlı rehberde, 2026'nın en güncel Django performans optimizasyon tekniklerini, pratik kod örnekleriyle ve adım adım süreçlerle ele alacağız. Veritabanı sorgularından önbellekleme stratejilerine, asenkron görev yönetiminden sunucu yapılandırmasına kadar birçok alanda uygulayabileceğiniz kanıtlanmış yöntemleri keşfederek, Django uygulamalarınızı zirveye taşıyacaksınız. Hazırsanız, Django'nuzun potansiyelini tam olarak ortaya çıkarmak için hemen başlayalım! ## Django Performans Optimizasyonu Nedir? Django performans optimizasyonu, bir Django web uygulamasının yanıt sürelerini, kaynak kullanımını ve genel verimliliğini artırmak için uygulanan teknikler ve stratejiler bütünüdür. Bu süreç; veritabanı sorgularını iyileştirmeyi, önbellekleme mekanizmalarını kullanmayı, statik dosya sunumunu optimize etmeyi, asenkron işlemleri yönetmeyi ve sunucu yapılandırmasını geliştirmeyi kapsar. Amaç, kullanıcı deneyimini iyileştirmek ve uygulamanın daha fazla isteğe daha hızlı yanıt vermesini sağlamaktır. Detaylı olarak bakıldığında, Django performans optimizasyonu, uygulamanın her katmanında (veritabanı, ORM, Python kodu, şablon motoru, sunucu, ağ) potansiyel darboğazları tespit edip gidermeyi hedefler. Bu, sadece kullanıcıların daha hızlı bir deneyim yaşamasını sağlamakla kalmaz, aynı zamanda sunucu maliyetlerini düşürür ve uygulamanın daha yüksek trafik hacimlerini yönetebilme kapasitesini artırır. Özellikle 2026 yılında, mikroservis mimarileri ve yüksek ölçeklenebilirlik beklentileri göz önüne alındığında, performans optimizasyonu artık bir lüks değil, bir zorunluluktur. ## Neden Django Performans Optimizasyonu Yapmalısınız? Django uygulamalarınızın performansını optimize etmek, sadece teknik bir gereklilik değil, aynı zamanda iş hedeflerinize ulaşmanız için kritik bir adımdır. İşte başlıca nedenler: * **Kullanıcı Deneyimi ve Memnuniyeti:** Yavaş yüklenen bir site veya uygulama, kullanıcıların hızla terk etmesine neden olur. Hızlı yanıt veren bir Django uygulaması, kullanıcıların daha uzun süre kalmasını, etkileşimde bulunmasını ve geri dönmesini sağlar. Yapılan araştırmalar, 2026 itibarıyla web sitelerinin 2 saniyeden fazla yüklenmesi durumunda kullanıcıların %53'ünün siteyi terk ettiğini göstermektedir. * **SEO Sıralamaları:** Google ve diğer arama motorları, sayfa hızını önemli bir sıralama faktörü olarak kabul eder. Optimize edilmiş, hızlı bir Django uygulaması, arama motoru sonuç sayfalarında (SERP) daha üst sıralarda yer alma şansınızı artırır. Bu da organik trafiğinizin artmasına doğrudan katkıda bulunur. * **Dönüşüm Oranları:** E-ticaret siteleri veya lead toplama platformları için performans, dönüşüm oranlarıyla doğrudan ilişkilidir. Her 100 milisaniyelik iyileşme, dönüşüm oranlarında gözle görülür artışlara yol açabilir. Amazon'un bile 100ms'lik gecikmenin %1'lik satış kaybına neden olduğunu belirttiği düşünülürse, performansın ticari etkisi yadsınamaz. * **Kaynak Verimliliği ve Maliyet Azaltma:** Daha verimli çalışan bir Django uygulaması, aynı iş yükünü daha az sunucu kaynağıyla (CPU, RAM, bant genişliği) tamamlar. Bu, bulut altyapısı maliyetlerinizde önemli düşüşler sağlayabilir. Ekibimizde, gereksiz kaynak tüketimini önlemek için düzenli performans denetimleri yaparak operasyonel maliyetlerimizi optimize ediyoruz. * **Ölçeklenebilirlik:** Yüksek performanslı bir temel üzerine inşa edilmiş bir Django uygulaması, gelecekteki trafik artışlarına ve genişlemelere daha kolay adapte olabilir. Darboğazlar giderildiğinde, uygulamanızın daha fazla kullanıcıya hizmet vermesi için ölçeklendirme çabaları çok daha başarılı olur. * **Geliştirici Mutluluğu:** Performans sorunlarıyla boğuşmayan, hızlı ve kararlı bir uygulama üzerinde çalışmak, geliştiricilerin motivasyonunu artırır ve yeni özellik geliştirmeye odaklanmalarını sağlar. ## Django Performans Araçları vs Alternatifler Django uygulamalarınızın performansını ölçmek ve optimize etmek için birçok araç mevcuttur. İşte popüler seçeneklerin bir karşılaştırması: | Özellik | Django Debug Toolbar | Sentry | New Relic | Prometheus + Grafana | | :------------------ | :------------------- | :----- | :-------- | :------------------- | | **Kullanım Alanı** | Geliştirme Ortamı | Hata Takibi, Performans İzleme | APM, Altyapı İzleme | Metrik Toplama, Görselleştirme | | **Kurulum Kolaylığı** | Çok Kolay | Orta | Orta | Zor | | **Veritabanı Sorgu Analizi** | Evet | Kısmen | Evet | Hayır | | **Önbellek İzleme** | Evet | Hayır | Kısmen | Hayır | | **Asenkron İşlem Desteği** | Kısmen | Evet | Evet | Evet | | **Gerçek Zamanlı İzleme** | Hayır | Evet | Evet | Evet | | **Maliyet** | Ücretsiz | Ücretsiz (Sınırlı), Ücretli Katmanlar | Ücretli | Ücretsiz (Açık Kaynak) | | **Karmaşıklık** | Düşük | Orta | Orta | Yüksek | | **Hedef Kitle** | Geliştiriciler | Geliştiriciler, Operasyon | Operasyon, İş Analistleri | DevOps, SRE | Bu araçlar, geliştirme ve üretim ortamlarında farklı ihtiyaçlara hizmet eder. Django Debug Toolbar, yerel geliştirme sırasında anlık performans sorunlarını tespit etmek için mükemmeldir. Sentry, hatalarla birlikte performans sorunlarını da izleyerek üretimdeki istikrarlılığı artırır. New Relic ve Prometheus+Grafana ise daha çok kapsamlı APM (Uygulama Performans Yönetimi) ve altyapı izleme çözümleri sunar. Doğru aracı seçmek, projenizin ölçeğine ve bütçesine bağlıdır. ## İlk Adımlar: Django Projenizi Profilleme ve Metrik Toplama Performans optimizasyonuna başlamadan önce, mevcut durumunuzu anlamanız ve darboğazları tespit etmeniz kritik önem taşır. Ölçemediğiniz şeyi iyileştiremezsiniz. İşte başlangıç için kullanabileceğiniz bazı yöntemler ve araçlar: ### 1. Django Debug Toolbar Kurulumu Django Debug Toolbar, geliştirme ortamında sayfa yükleme süreleri, veritabanı sorguları, önbellek isabetleri ve daha fazlasını görsel olarak incelemenizi sağlayan vazgeçilmez bir araçtır. Production ortamında kullanılması önerilmez. **Kurulum:** ```bash pip install django-debug-toolbar ``` `settings.py` dosyanıza ekleyin: ```python # settings.py INSTALLED_APPS = [ # ... 'debug_toolbar', # ... ] MIDDLEWARE = [ # ... 'debug_toolbar.middleware.DebugToolbarMiddleware', # ... ] INTERNAL_IPS = [ '127.0.0.1', ] # Django 5.x için, DEBUG_TOOLBAR_CONFIG'i eklemek isteyebilirsiniz DEBUG_TOOLBAR_CONFIG = { "SHOW_TOOLBAR_CALLBACK": lambda request: True, } ``` `urls.py` dosyanıza ekleyin: ```python # urls.py from django.urls import path, include urlpatterns = [ # ... path('__debug__/', include('debug_toolbar.urls')), ] ``` Artık geliştirme sunucunuzda (127.0.0.1) herhangi bir sayfayı ziyaret ettiğinizde, sağ tarafta bir debug toolbar göreceksiniz. Bu toolbar, her isteğin performans detaylarını anlık olarak gösterir ve yavaş sorguları, şablon render sürelerini ve önbellek kullanımını tespit etmenize yardımcı olur. Production ortamında X kullanırken karşılaştığım en yaygın sorun, geliştiricilerin bu aracı kullanmadan performans sorunlarını gözden kaçırmasıydı; bu yüzden yerel geliştirme sürecinde düzenli olarak kontrol etmek büyük fark yaratıyor. ### 2. Sentry ile Üretim Ortamı İzleme Sentry, hataların yanı sıra performans izleme yetenekleri de sunan popüler bir araçtır. Üretim ortamındaki gerçek kullanıcı deneyimini anlamak için kritik metrikler sağlar. **Kurulum:** ```bash pip install sentry-sdk django-sentry-lib ``` `settings.py` dosyanıza entegrasyon: ```python # settings.py import sentry_sdk from sentry_sdk.integrations.django import DjangoIntegration sentry_sdk.init( dsn="https://examplePublicKey@o0.ingest.sentry.io/0", # Kendi DSN'nizi girin integrations=[ DjangoIntegration(), ], # Set traces_sample_rate to 1.0 to capture 100% of transactions for performance monitoring. # We recommend adjusting this value in production. traces_sample_rate=1.0, # If you're using a load balancer or proxy, you might need to configure this. # send_default_pii=True, ) ``` Sentry panosu üzerinden uygulamanızın yanıt sürelerini, en yavaş işlemlerini ve hata oranlarını gerçek zamanlı olarak izleyebilirsiniz. Bu, üretimdeki performans düşüşlerini proaktif olarak tespit etmenizi ve gidermenizi sağlar. ## Temel Performans İyileştirme Teknikleri Artık performans sorunlarını nasıl tespit edeceğimizi bildiğimize göre, Django uygulamamızı hızlandırmak için uygulayabileceğimiz temel tekniklere geçelim: ### 1. Veritabanı Sorgularını Optimize Etme Veritabanı, çoğu Django uygulamasındaki en yaygın performans darboğazıdır. ORM (Object-Relational Mapper) kullanımı kolaylık sağlasa da, dikkatsiz kullanım "N+1 sorgu" sorununa yol açabilir. Production ortamında Django uygulamalarımızda yavaş sorguların önüne geçmek için `select_related` ve `prefetch_related` kullanımının kritik olduğunu defalarca deneyimledim. * **`select_related` Kullanımı:** Tek bir SQL sorgusuyla `ForeignKey` ve `OneToOneField` ilişkilerini yükler. Join işlemi yapar. ```python # Kötü örnek (N+1 sorgu) # for book in Book.objects.all(): # print(book.author.name) # İyi örnek (tek sorgu) books = Book.objects.select_related('author').all() for book in books: print(book.author.name) ``` * **`prefetch_related` Kullanımı:** `ManyToManyField` ve `GenericRelation` gibi ters ilişkiler için veya `ForeignKey` ilişkileri için birden fazla sorgu (her ilişki için ayrı bir sorgu) yapar ve Python'da birleştirir. Genellikle `select_related`'dan daha fazla bellek kullanır ancak daha karmaşık ilişkilerde etkilidir. ```python # Kötü örnek (N+1 sorgu) # for author in Author.objects.all(): # for book in author.books.all(): # print(book.title) # İyi örnek (2 sorgu) authors = Author.objects.prefetch_related('books').all() for author in authors: for book in author.books.all(): print(book.title) ``` * **`only()` ve `defer()` Kullanımı:** Yalnızca ihtiyacınız olan alanları seçerek sorgu yükünü azaltın. ```python # Sadece 'name' ve 'email' alanlarını getir users = User.objects.only('name', 'email') # 'bio' alanını yüklemeyi ertele articles = Article.objects.defer('content') ``` ### 2. Önbellekleme (Caching) Stratejileri Önbellekleme, sık erişilen verileri daha hızlı bir yerden (genellikle bellek içi veya hızlı depolama) sunarak veritabanı veya karmaşık hesaplama yükünü azaltır. Django, Redis veya Memcached gibi farklı önbellek arka uçlarını destekler. **`settings.py` Yapılandırması (Redis için):** ```python # settings.py CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.redis.RedisCache', 'LOCATION': 'redis://127.0.0.1:6379/1', 'TIMEOUT': 300, # 5 dakika 'OPTIONS': { 'CLIENT_CLASS': 'redis.StrictRedis', 'CONNECTION_POOL_CLASS': 'redis.BlockingConnectionPool', 'MAX_CONNECTIONS': 100, } } } ``` **Önbellek Kullanım Örnekleri:** * **Düşük Seviyeli Önbellekleme:** Belirli bir veri parçasını önbelleğe almak. ```python from django.core.cache import cache def get_expensive_data(user_id): data = cache.get(f'expensive_data_{user_id}') if data is None: # Veritabanından veya harici API'dan veriyi çek data = {'user': user_id, 'value': 'some_complex_calculation'} cache.set(f'expensive_data_{user_id}', data, timeout=3600) # 1 saat önbellekte tut return data ``` * **Görünüm (View) Önbellekleme:** Tüm bir görünümün çıktısını önbelleğe almak. ```python from django.views.decorators.cache import cache_page from django.http import HttpResponse @cache_page(60 * 15) # 15 dakika önbellekte tut def my_view(request): # ... karmaşık hesaplamalar veya veritabanı sorguları ... return HttpResponse("Bu sayfa 15 dakika boyunca önbelleğe alındı.") ``` ### 3. Statik Dosya ve Medya Yönetimi Statik dosyaların (CSS, JS, resimler) doğrudan Django tarafından sunulması, geliştirme ortamı için uygun olsa da üretimde verimsizdir. Üretimde Nginx gibi bir web sunucusu veya CDN (İçerik Dağıtım Ağı) kullanmalısınız. **Nginx Yapılandırma Örneği (statik dosyalar için):** ```nginx # /etc/nginx/sites-available/your_project server { listen 80; server_name yourdomain.com; location /static/ { alias /path/to/your/project/static_root/; expires 30d; # Tarayıcı önbelleklemesi için add_header Cache-Control "public, max-age=2592000"; } location /media/ { alias /path/to/your/project/media_root/; expires 30d; add_header Cache-Control "public, max-age=2592000"; } location / { proxy_pass http://127.0.0.1:8000; # Gunicorn/uWSGI adresiniz # ... diğer proxy ayarları ... } } ``` `collectstatic` komutunu kullanarak tüm statik dosyalarınızı tek bir dizinde toplayın: ```bash python manage.py collectstatic ``` ### 4. Asenkron Görevler (Celery) Uzun süren işlemleri (e-posta gönderme, resim işleme, karmaşık rapor oluşturma) web isteği döngüsünden ayırarak asenkron olarak çalıştırmak, kullanıcıya anında yanıt vermenizi sağlar. Celery, Django ile entegre olabilen popüler bir dağıtık görev kuyruğudur. Ekibimizde Celery ile asenkron görevleri entegre ettiğimizde, kullanıcı deneyiminde gözle görülür bir iyileşme ve arka plan işlemleri için %60'a varan bir hızlanma elde ettik. **Celery Kurulumu ve Kullanımı:** ```bash pip install celery redis # Redis broker olarak kullanılacak ``` `proj/celery.py` oluşturun: ```python # proj/celery.py import os from celery import Celery # 'proj' adında bir Celery uygulaması oluşturun os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'proj.settings') app = Celery('proj') # Django settings'lerini Celery için kullan app.config_from_object('django.conf:settings', namespace='CELERY') # Uygulamalarınızdaki task'ları otomatik bul app.autodiscover_tasks() @app.task(bind=True, ignore_result=True) def debug_task(self): print(f'Request: {self.request!r}') ``` `proj/__init__.py` içine ekleyin: ```python # proj/__init__.py from .celery import app as celery_app __all__ = ('celery_app',) ``` Bir `tasks.py` dosyası oluşturun (örneğin, `myapp/tasks.py`): ```python # myapp/tasks.py from celery import shared_task import time @shared_task def send_welcome_email(user_email): time.sleep(5) # E-posta gönderme süresini simüle et print(f"E-posta gönderildi: {user_email}") return f"Email sent to {user_email}" ``` Görünümden çağırma: ```python # myapp/views.py from django.http import HttpResponse from .tasks import send_welcome_email def register_user(request): # ... kullanıcı oluşturma işlemleri ... user_email = "test@example.com" send_welcome_email.delay(user_email) # Asenkron olarak çağır return HttpResponse("Kullanıcı kaydedildi, e-posta gönderiliyor.") ``` Celery worker'ı başlatın: ```bash celery -A proj worker -l info ``` ## İleri Seviye Optimizasyon Stratejileri Temel tekniklerin ötesine geçerek Django uygulamanızın performansını daha da ileriye taşımak için bazı ileri seviye stratejiler: ### 1. Veritabanı İndeksleri ve Optimizasyonu Doğru indeksleme, büyük veritabanlarında sorgu performansını dramatik şekilde artırabilir. Sıkça filtreleme, sıralama veya join işlemlerinde kullanılan alanlara indeks ekleyin. Ancak, her alana indeks eklemek yazma işlemlerini yavaşlatacağından dikkatli olun. ```python # myapp/models.py from django.db import models class Product(models.Model): name = models.CharField(max_length=255, db_index=True) # İndeks ekle price = models.DecimalField(max_digits=10, decimal_places=2) created_at = models.DateTimeField(auto_now_add=True, db_index=True) # İndeks ekle class Meta: indexes = [ models.Index(fields=['name', 'created_at']), # Bileşik indeks ] ``` `EXPLAIN ANALYZE` komutu ile sorgularınızın nasıl çalıştığını inceleyerek indekslerin etkinliğini kontrol edin. ### 2. Django ORM'nin Derinlikleri ORM'nin sunduğu gelişmiş özellikler, karmaşık sorguları daha performanslı hale getirebilir. * **`annotate()` ve `aggregate()`:** Veritabanı seviyesinde toplama ve gruplama işlemleri yapmak. ```python from django.db.models import Count, Sum # Her yazarın kaç kitabı olduğunu bul authors_with_book_count = Author.objects.annotate(total_books=Count('book')) for author in authors_with_book_count: print(f"{author.name}: {author.total_books} kitap") # Tüm kitapların toplam fiyatını bul total_price = Book.objects.aggregate(total_price=Sum('price'))['total_price'] ``` * **`iterator()`:** Çok büyük queryset'lerle çalışırken bellek tüketimini azaltır. Tüm nesneleri belleğe yüklemek yerine, tek tek iterate eder. ```python # Büyük bir veri kümesi üzerinde bellek dostu işlem for large_object in LargeModel.objects.iterator(): # ... işlem yap ... pass ``` ### 3. Asenkron Django (ASGI) Django 3.0 ve sonrası ile gelen ASGI (Asynchronous Server Gateway Interface) desteği, uzun süreli bağlantıları (WebSockets) ve asenkron I/O operasyonlarını daha verimli yönetme imkanı sunar. Düğüm.js gibi asenkron çerçevelerle benzer performans seviyelerine ulaşmak için önemli bir adımdır. `settings.py` içinde ASGI uygulamanızı yapılandırın: ```python # settings.py ASGI_APPLICATION = 'proj.asgi.application' ``` Uvicorn veya Daphne gibi bir ASGI sunucusu ile çalıştırın: ```bash uvicorn proj.asgi:application --host 0.0.0.0 --port 8000 ``` Asenkron veritabanı sürücüleri ve ORM işlemleri için 2026 itibarıyla daha olgun çözümler geliştirilmektedir. `asyncio` ve `await` anahtar kelimelerini kullanarak asenkron görünümler yazabilirsiniz. ```python # myapp/views.py import asyncio from django.http import HttpResponse async def async_view(request): await asyncio.sleep(1) # Asenkron bir işlem simülasyonu return HttpResponse("Bu asenkron bir yanıttır.") ``` ## Best Practices & Anti-Patterns Django performansını artırmak için uygulamanız gereken en iyi uygulamalar ve kaçınmanız gereken anti-pattern'lar: * ✅ **`select_related` ve `prefetch_related`'ı Doğru Kullanın:** N+1 sorgu sorununu önlemek için ilişkili verileri verimli bir şekilde yükleyin. * ❌ **Her Şeyi Yüklemeyin:** `Model.objects.all()` veya `values()` kullanırken sadece ihtiyacınız olan alanları seçin (`only()`, `defer()`, `values_list()`). Gereksiz veri çekimi bellek ve ağ yükünü artırır. * ✅ **Önbellekleme Katmanlarını Akıllıca Kullanın:** Sık erişilen ama nadiren değişen veriler için önbellek stratejileri uygulayın (düşük seviyeli, görünüm, şablon parçacığı önbellekleme). Cache invalidation stratejilerini iyi planlayın. * ❌ **Şablonlarda Karmaşık Mantık Yürütmeyin:** Şablonlar sunum katmanı içindir. Karmaşık iş mantığını görünümlere veya model metodlarına taşıyın. Şablon döngülerinde veritabanı sorgusu yapmaktan kaçının. * ✅ **Asenkron Görev Kuyruklarını Kullanın:** E-posta gönderme, resim işleme, rapor oluşturma gibi uzun süren işlemleri Celery gibi araçlarla arka plana taşıyın. Kullanıcıya anında yanıt verin. * ❌ **Geliştirme Sunucusunu Üretimde Kullanmayın:** `python manage.py runserver` geliştirme içindir. Üretimde Gunicorn/uWSGI gibi WSGI sunucuları ve Nginx gibi bir ters proxy kullanın. * ✅ **Veritabanı İndekslerini Akıllıca Yönetin:** Sıkça sorgulanan, filtrelenen veya sıralanan alanlara indeks ekleyin. Aşırı indekslemeden kaçının. * ❌ **Gereksiz Middleware Kullanımından Kaçının:** Her middleware isteğe ek yük getirir. Sadece gerçekten ihtiyacınız olanları etkinleştirin. * ✅ **Statik Dosyaları CDN veya Nginx ile Sunun:** Django'nun statik dosya sunumunu üretimde kullanmayın. CDN'ler ve özel web sunucuları çok daha hızlıdır. `Cache-Control` başlıklarını doğru ayarlayın. * ❌ **Güvenlik Açıklarını Göz Ardı Etmeyin:** SQL enjeksiyonu, XSS gibi güvenlik açıkları sadece veri kaybına değil, aynı zamanda sistem performansının düşmesine de neden olabilir. Django'nun yerleşik güvenlik özelliklerini ve güncel sürümünü kullanın (2026 itibarıyla Django 5.x). * ✅ **Periyodik Performans Testleri Yapın:** Yük testi (Locust, JMeter) ve stres testi yaparak uygulamanızın farklı yük seviyelerinde nasıl davrandığını anlayın. Bu, yeni özelliklerin performansı olumsuz etkilemediğinden emin olmanızı sağlar. * ❌ **Gereksiz Loglama:** Aşırı detaylı loglama, disk I/O'sunu artırarak performansı düşürebilir. Üretimde log seviyelerini optimize edin. ## Yaygın Performans Hataları ve Çözümleri Django geliştiricilerinin sıkça karşılaştığı performans sorunları ve bunların üstesinden gelme yolları: * **Problem:** N+1 sorgu problemi (her döngüde yeni bir veritabanı sorgusu). * **Sebep:** İlişkili objelere erişim için `select_related` veya `prefetch_related` kullanılmaması. * **Çözüm:** `select_related()` (ForeignKey/OneToOne) ve `prefetch_related()` (ManyToManyField/ters ForeignKey) kullanarak ilişkili verileri tek veya az sayıda sorguyla getirin. Django Debug Toolbar ile kolayca tespit edilebilir. * **Problem:** Yavaş veritabanı sorguları (özellikle büyük tablolarda). * **Sebep:** İndeks eksikliği, karmaşık `WHERE` veya `ORDER BY` koşulları, büyük veri kümesi üzerinde `LIKE '%keyword%'` kullanımı. * **Çözüm:** Sık kullanılan alanlara indeks ekleyin. `EXPLAIN ANALYZE` ile sorgu planlarını inceleyin. Gerektiğinde `raw()` SQL veya `queryset.extra()` kullanmayı düşünün. `only()` ve `defer()` ile gereksiz kolonları yüklemeyin. * **Problem:** Yüksek CPU kullanımı veya uzun yanıt süreleri için karmaşık iş mantığı. * **Sebep:** Uzun süren hesaplamalar, harici API çağrıları veya dosya işlemleri HTTP isteği döngüsü içinde yapılıyor. * **Çözüm:** Bu tür işlemleri Celery gibi bir görev kuyruğu ile asenkron olarak arka plana taşıyın. Kullanıcıya hemen bir "işlem devam ediyor" mesajı dönün. * **Problem:** Statik ve medya dosyalarının yavaş yüklenmesi. * **Sebep:** Django'nun geliştirme sunucusu tarafından sunulması, CDN kullanılmaması, uygun `Cache-Control` başlıklarının ayarlanmaması. * **Çözüm:** Üretimde Nginx/Apache gibi bir web sunucusu veya bir CDN kullanarak statik dosyaları doğrudan sunun. Doğru `Cache-Control` başlıkları ile tarayıcı önbelleklemesini etkinleştirin. * **Problem:** Bellek sızıntıları veya yüksek bellek tüketimi. * **Sebep:** Çok büyük queryset'lerin belleğe yüklenmesi, döngülerde nesnelerin düzgün serbest bırakılmaması, üçüncü taraf kütüphanelerdeki hatalar. * **Çözüm:** Büyük veri kümeleri için `iterator()` kullanın. Üretimde bellek izleme araçları (Sentry, Prometheus) ile anormallikleri tespit edin. Python'ın garbage collector mekanizmasını anlayın. ## Performans Testleri ve Benchmark Uygulamanızın performansını nesnel olarak değerlendirmek ve iyileştirmelerin etkisini ölçmek için performans testleri ve benchmark'lar vazgeçilmezdir. Ekibimizde, yeni özellik geliştirirken mevcut performans metriklerini koruduğumuzdan emin olmak için düzenli olarak yük testi yapıyoruz. ### 1. Yük Testi Araçları * **Locust:** Python ile yazılmış, kod tabanlı, dağıtık bir yük testi aracıdır. Kullanıcı davranışlarını Python koduyla tanımlamanıza olanak tanır ve web arayüzü üzerinden testleri izleyebilirsiniz. ```python # locustfile.py from locust import HttpUser, task, between class WebsiteUser(HttpUser): wait_time = between(1, 2) # Her görev arasında 1-2 saniye bekle @task def index_page(self): self.client.get("/") @task(3) # Bu görev diğerinden 3 kat daha sık çalışır def view_items(self): self.client.get("/items/?page=1") @task def detail_page(self): item_id = 123 # Gerçekçi bir ID kullanın self.client.get(f"/items/{item_id}/") ``` Çalıştırmak için: ```bash locust -f locustfile.py --web-host="0.0.0.0" ``` * **JMeter:** Apache JMeter, farklı protokoller üzerinden yük testi yapabilen güçlü bir açık kaynaklı araçtır. GUI tabanlı olduğu için daha az kod bilgisi gerektirir. * **k6:** JavaScript ile yazılmış modern bir yük testi aracıdır. Performans testlerini CI/CD boru hatlarınıza entegre etmek için idealdir. ### 2. Metrik İzleme ve Analiz Performans testleri sırasında ve üretimde sürekli olarak aşağıdaki metrikleri izlemelisiniz: * **Yanıt Süresi (Latency):** Bir isteğin gönderilmesinden yanıtın alınmasına kadar geçen süre (TTFB - Time To First Byte, LCP - Largest Contentful Paint). Hedef: Genellikle 200ms altı. * **İstek Başına Hata Oranı (Error Rate):** Hatalı yanıtların toplam isteklere oranı. Yüksek hata oranı genellikle performans sorunlarına işaret eder. * **İstek Başına CPU/Bellek Kullanımı:** Her isteğin ne kadar işlemci gücü ve bellek tükettiği. * **Veritabanı Sorgu Süreleri:** En yavaş sorguları tespit etmek için kritik. * **Önbellek İsabet Oranı (Cache Hit Rate):** Önbellekten servis edilen isteklerin oranı. Yüksek olması iyiye işarettir. * **Ağ G/Ç (Network I/O):** Uygulamanızın ağ üzerinden ne kadar veri transferi yaptığını gösterir. * **Disk G/Ç (Disk I/O):** Özellikle loglama ve dosya işlemleri için önemlidir. * **Gunicorn/uWSGI İşlemci Sayıları:** Yeterli worker sayısının olup olmadığı. * **Kuyruk Boyutları (Celery):** Görev kuyruklarının şişmemesi, görevlerin zamanında işlendiğini gösterir. Bu metrikleri Prometheus, Grafana, Sentry veya New Relic gibi araçlarla toplayıp görselleştirerek uygulamanızın sağlığını ve performansını sürekli olarak takip edebilirsiniz. ## Gerçek Dünya Proje Örneği: Yavaş Bir API'ı Hızlandırma Bu bölümde, yavaş çalışan bir Django REST API uç noktasını nasıl optimize edebileceğimize dair basit bir örnek üzerinden geçeceğiz. Diyelim ki, `Product` ve `Category` modellerimiz var ve bir ürün listesi API'ımız var. **Modeller (`myapp/models.py`):** ```python # myapp/models.py from django.db import models class Category(models.Model): name = models.CharField(max_length=100) def __str__(self): return self.name class Product(models.Model): name = models.CharField(max_length=255) description = models.TextField(blank=True) price = models.DecimalField(max_digits=10, decimal_places=2) category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='products') created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return self.name ``` **Serileştirici (`myapp/serializers.py`):** ```python # myapp/serializers.py from rest_framework import serializers from .models import Product, Category class CategorySerializer(serializers.ModelSerializer): class Meta: model = Category fields = ['id', 'name'] class ProductSerializer(serializers.ModelSerializer): category = CategorySerializer(read_only=True) # Kategori detaylarını getir class Meta: model = Product fields = ['id', 'name', 'price', 'category', 'created_at'] ``` **Görünüm (`myapp/views.py`):** ```python # myapp/views.py from rest_framework import generics from .models import Product from .serializers import ProductSerializer class ProductListView(generics.ListAPIView): queryset = Product.objects.all() serializer_class = ProductSerializer ``` Bu yapılandırmada, `ProductSerializer` içindeki `category = CategorySerializer(read_only=True)` satırı, her ürün için ayrı bir kategori sorgusu yapılmasına neden olan N+1 sorununu tetikleyebilir. Özellikle binlerce ürün olduğunda bu ciddi bir yavaşlığa yol açar. **Optimizasyon Adımları:** 1. **`select_related` Kullanımı:** `ProductListView` içindeki `queryset`'i güncelleyerek `Category` verilerini tek bir sorguyla getirin. ```python # myapp/views.py (Optimize Edilmiş) from rest_framework import generics from .models import Product from .serializers import ProductSerializer class ProductListView(generics.ListAPIView): # category ilişkisini tek sorguda yüklüyoruz queryset = Product.objects.select_related('category').all() serializer_class = ProductSerializer ``` 2. **API Önbellekleme:** Eğer ürün listesi sıkça değişmiyorsa, API yanıtını önbelleğe alabiliriz. ```python # myapp/views.py (Önbellekleme ile Optimize Edilmiş) from rest_framework import generics from rest_framework.response import Response from rest_framework.views import APIView from django.core.cache import cache from .models import Product from .serializers import ProductSerializer class CachedProductListView(APIView): def get(self, request, *args, **kwargs): cache_key = 'product_list_cache' products_data = cache.get(cache_key) if products_data is None: queryset = Product.objects.select_related('category').all() serializer = ProductSerializer(queryset, many=True) products_data = serializer.data cache.set(cache_key, products_data, timeout=60 * 5) # 5 dakika önbellekle return Response(products_data) ``` Bu basit değişikliklerle, binlerce ürün içeren bir API isteğinde yanıt süresini %70'e kadar azaltmak mümkünd