در این فصل روشهای مختلف بهینهسازی کوئریها، مدیریت عملکرد، و کار با دادههای سنگین در Django ORM بررسی میشود. هدف اصلی این است که از منابع پایگاه داده به بهترین نحو استفاده کنیم و عملکرد برنامه را بهبود دهیم.
برای کاهش تعداد کوئریهای مربوط به روابط ForeignKey یا OneToOne، از این متد استفاده میشود. این متد با انجام یک کوئری واحد، دادههای مرتبط را بازیابی میکند.
from myapp.models import Order
# بدون select_related (تعداد زیادی کوئری جداگانه اجرا میشود)
orders = Order.objects.all()
for order in orders:
print(order.customer.name) # هر بار کوئری جدید به پایگاه داده زده میشود
# با select_related (یک کوئری واحد اجرا میشود)
orders = Order.objects.select_related('customer').all()
for order in orders:
print(order.customer.name) # دادهها با یک کوئری بهینه بازیابی میشوند
این متد برای بهینهسازی روابط ManyToMany یا Reverse ForeignKey استفاده میشود. برخلاف select_related
که از JOIN استفاده میکند، prefetch_related
دادههای مورد نیاز را در چندین کوئری جداگانه پیشبارگذاری میکند و سپس آنها را به هم مرتبط میکند.
from myapp.models import Author
# بدون prefetch_related (تعداد زیادی کوئری اضافی)
authors = Author.objects.all()
for author in authors:
print([book.title for book in author.books.all()]) # یک کوئری جدید برای هر نویسنده اجرا میشود
# با prefetch_related (بهینهسازی کوئریها)
authors = Author.objects.prefetch_related('books').all()
for author in authors:
print([book.title for book in author.books.all()]) # دادهها از قبل بارگذاری شدهاند
این متدها به شما امکان میدهند فیلدهای خاصی را از پایگاه داده انتخاب کنید یا برخی از فیلدها را به تأخیر بیندازید.
only()
: فقط فیلدهای مشخصشده را بازیابی میکند.defer()
: تمام فیلدها بهجز فیلدهای مشخصشده بازیابی میشوند.
from myapp.models import Product
# فقط نام و قیمت را بازیابی کنید
products = Product.objects.only('name', 'price')
for product in products:
print(product.name, product.price) # فقط فیلدهای name و price بارگذاری میشوند
# همه فیلدها بهجز description بازیابی میشوند
products = Product.objects.defer('description')
for product in products:
print(product.name, product.price) # فیلد description هنگام دسترسی بارگذاری میشود
برای افزودن فیلدهای محاسباتی به کوئریها، از این متد استفاده میشود. این فیلدها بر اساس دادههای پایگاه داده محاسبه میشوند.
from django.db.models import Count
from myapp.models import Author
# شمارش تعداد کتابهای هر نویسنده
authors = Author.objects.annotate(book_count=Count('books'))
for author in authors:
print(author.name, author.book_count) # تعداد کتابهای هر نویسنده
این متدها فقط دادههای خاصی را بازیابی میکنند و خروجی به صورت دیکشنری یا لیست خواهد بود.
from myapp.models import Product
# استفاده از values()
products = Product.objects.values('name', 'price')
for product in products:
print(product['name'], product['price']) # خروجی به صورت دیکشنری
# استفاده از values_list()
products = Product.objects.values_list('name', 'price')
for product in products:
print(product[0], product[1]) # خروجی به صورت لیست
برای کاهش مصرف حافظه هنگام پردازش دادههای بزرگ، از این متد برای تکرار تدریجی دادهها استفاده میشود.
from myapp.models import LargeData
# پردازش تدریجی دادهها
for data in LargeData.objects.all().iterator():
print(data.name) # دادهها به صورت تدریجی از پایگاه داده بازیابی میشوند
برای بازیابی تعداد محدودی از نتایج یا پرش از تعدادی از رکوردها، از slicing استفاده کنید.
from myapp.models import Product
# دریافت ۱۰ رکورد اول
products = Product.objects.all()[:10]
for product in products:
print(product.name)
# پرش از ۱۰ رکورد اول و دریافت ۱۰ رکورد بعدی
products = Product.objects.all()[10:20]
for product in products:
print(product.name)
برای دیباگ کردن کوئریهای تولیدشده توسط Django ORM، از این ویژگی استفاده کنید.
from myapp.models import Product
# نمایش کوئری تولیدشده
query = Product.objects.filter(price__gt=100).query
print(query) # نمایش کوئری SQL
- از
select_related
وprefetch_related
برای کاهش کوئریهای اضافی استفاده کنید. - با
only
وdefer
دادههای غیرضروری را از کوئریها حذف کنید. - برای دادههای بزرگ از
iterator
و محدودیتهایlimit
وoffset
استفاده کنید. - برای بررسی کارایی، از ابزارهایی مثل django-debug-toolbar استفاده کنید.
- در پروژههای بزرگ، از ابزارهای پروفایلینگ و مانیتورینگ کوئریها بهره ببرید.