Syntax | سینتکس
روشی که خودم برای حل این مشکل استفاده میکنم به این شکل است که اون آبجکت دیتابیس رو لاک میکنم تا تغییرات رو انجام بدم و بقیه ترد ها در اون لحظه دسترسی نداشته باشن. توی جنگجو به این صورت پیاده می شه. سوال: چرا من instance = cls.objects.select_for_update()…
جواب سوالی که تو این پست پرسیدم رو یکی از دوستان توی کامنت گفتن.
اما چرا orm چنین کاری رو انجام میده؟
دلیل اصلی این رفتار در بیشتر ORMها، بهینهسازی عملکرد و کاهش تعداد کوئریهای ارسالی به دیتابیس است.
زمانی که شما یک کوئری را در ORM میسازید، ORM آن را به صورت یک نمونه از یک کلاس مدل (Model) در نظر میگیرد. این کلاس مدل شامل اطلاعاتی است که برای انجام کوئری مورد نیاز است، مانند شرایط جستجو، مقادیر بروزرسانی و غیره. اما کوئری به صورت واقعی به دیتابیس ارسال نمیشود تا زمانی که شما درخواستی برای دستیابی به نتیجه کوئری داشته باشید.
به طور کلی، این رویکرد در ORMها بهبود عملکرد، قابلیت تغییرپذیری و امنیت را بهبود میبخشد. با این حال، ممکن است در برخی موارد نیاز داشته باشید کوئری را فوراً به دیتابیس ارسال کنید، برخی ORMها امکاناتی برای این منظور فراهم میکنند. به عنوان مثال، ممکن است بتوانید از متدی مانند
#orm
@citax_tel 👈 سیتاکس
اما چرا orm چنین کاری رو انجام میده؟
دلیل اصلی این رفتار در بیشتر ORMها، بهینهسازی عملکرد و کاهش تعداد کوئریهای ارسالی به دیتابیس است.
زمانی که شما یک کوئری را در ORM میسازید، ORM آن را به صورت یک نمونه از یک کلاس مدل (Model) در نظر میگیرد. این کلاس مدل شامل اطلاعاتی است که برای انجام کوئری مورد نیاز است، مانند شرایط جستجو، مقادیر بروزرسانی و غیره. اما کوئری به صورت واقعی به دیتابیس ارسال نمیشود تا زمانی که شما درخواستی برای دستیابی به نتیجه کوئری داشته باشید.
به طور کلی، این رویکرد در ORMها بهبود عملکرد، قابلیت تغییرپذیری و امنیت را بهبود میبخشد. با این حال، ممکن است در برخی موارد نیاز داشته باشید کوئری را فوراً به دیتابیس ارسال کنید، برخی ORMها امکاناتی برای این منظور فراهم میکنند. به عنوان مثال، ممکن است بتوانید از متدی مانند
.execute()
در ORM استفاده کنید تا کوئری را بدون تأخیر ارسال کنید. همچنین، برخی ORMها ممکن است حالتهایی برای اجرای فوری کوئریها، مانند حالت تراکنش (Transaction)، ارائه دهند.#orm
@citax_tel 👈 سیتاکس
👍6
چند نکته طلایی موقعی که دارید از django orm استفاده می کنید.
(قسمت اول)
1. کوئری ست هارو کاربردی بزنید:
از filters و annotations و aggregation استفاده کنید تا فیلد هایی که نیاز دراید رو با کمترین سربار دریافت کنید.
همچنین از متد defer و only برای محدود کردن فیلد هایی که قراره از دیتابیس بگیرید استفاده کنید تا optimize تر بشه کوئری شما و همچنین مصرف مموری نیز کمتر بشه.
2. ایندکس کردن:
استفاده کردن از ایندکس کلید افزایش کارامدی و سرعت کوئری های شما هستش.
هر فیلدی که قراره زیاد توی Where استفاده کنید رو پیشنهاد میشه ایندکس کنید.
همچنین ممکنه ایندکس کردن مخرب هم باشه. به این لینک سر بزنید:
https://python.plainenglish.io/mastering-the-art-of-meeting-database-indexing-needs-8b891e74794b
3. کوئری ها بصورت defer اجرا میشن!!
جنگو orm از این روش استفاده می کند تا کوئری ها تنها زمانی اجرا بشن که شما بهشون نیاز دارید. یعنی وقتی شما مینویسید
users = User.objects.all()
این کوئری اجرا نمیشود، تا زمانی که شما از مقدار users استفاده کنید.
همچنین اگه شما حواستون نباشه ممکنه یک اشتباه خیلی بزرگ انجام بدید. به مثال زیر دقت کنید:
تو این مثال هربار که blog.author رو میزنیم، یک hint سمت دیتابیس زده میشه.
4. از select_related و prefetch_related استفاده کنید.
این دو متد میتونن وقتی که توی مدلتون related دارید، تعداد کوئری هایی که سمت دیتابیس زده میشن رو خیلی کاهش بدن.
از select_related زمانی استفاده میشه که شما یک تک رابطه دارید. و از prefetch_related زمانی استفاده میشه که شما چندین رابطه دارید. مثلا:
5. از n + 1 اجتناب کنید!
مشکل n + 1 زمانی اتفاق میوفته که شما میخواید مجموعه از آبجکت هارو بگیرید. مثلا فرض کنید مدل پست رو داریم. مدل پست n تا کامنت داره.
زمانی که شما میخواید تک تک کامنت هارو بگیرید و اطلاعاتش رو نشون بدید با n + 1 مواجه میشوید.
یک یعنی کوئری که برای گرفتن پست زده شده، و n تعداد کوئری هایی که برای گرفتن کامنت ها زده شده. از این قبیل مشکلات رو خیلی راحت میتونیم با select_related و prefetch_related برطرف کنیم و با یک کوئری اطلاعات تمامی کامنت هارو هم بگیریم(این رو هم در نظر بگیرید هر چقدر کامنت ها بیشتر باشه، کوئری که میزنیم سنگین تر میشه).
link
#django #orm
@Syntax_fa
(قسمت اول)
1. کوئری ست هارو کاربردی بزنید:
از filters و annotations و aggregation استفاده کنید تا فیلد هایی که نیاز دراید رو با کمترین سربار دریافت کنید.
همچنین از متد defer و only برای محدود کردن فیلد هایی که قراره از دیتابیس بگیرید استفاده کنید تا optimize تر بشه کوئری شما و همچنین مصرف مموری نیز کمتر بشه.
# Fetches specific fields to avoid unneccessory fields fetch and store into the memory
blogs = Blog.objects.only('title', 'is_active').filter(category='tech')
2. ایندکس کردن:
استفاده کردن از ایندکس کلید افزایش کارامدی و سرعت کوئری های شما هستش.
هر فیلدی که قراره زیاد توی Where استفاده کنید رو پیشنهاد میشه ایندکس کنید.
# Adding an index to the "category" column for faster searches via category
class Blog(models.Model):
title = models.CharField(max_length=100)
category = models.CharField(max_length=50, db_index=True)
# ...
همچنین ممکنه ایندکس کردن مخرب هم باشه. به این لینک سر بزنید:
https://python.plainenglish.io/mastering-the-art-of-meeting-database-indexing-needs-8b891e74794b
3. کوئری ها بصورت defer اجرا میشن!!
جنگو orm از این روش استفاده می کند تا کوئری ها تنها زمانی اجرا بشن که شما بهشون نیاز دارید. یعنی وقتی شما مینویسید
users = User.objects.all()
این کوئری اجرا نمیشود، تا زمانی که شما از مقدار users استفاده کنید.
همچنین اگه شما حواستون نباشه ممکنه یک اشتباه خیلی بزرگ انجام بدید. به مثال زیر دقت کنید:
# Queries are executed when data is actually needed, minimizing unnecessary hits
blogs = Blog.objects.all()
for blog in blogs:
print(blog.author) # Each blog's author query is executed here
تو این مثال هربار که blog.author رو میزنیم، یک hint سمت دیتابیس زده میشه.
4. از select_related و prefetch_related استفاده کنید.
این دو متد میتونن وقتی که توی مدلتون related دارید، تعداد کوئری هایی که سمت دیتابیس زده میشن رو خیلی کاهش بدن.
از select_related زمانی استفاده میشه که شما یک تک رابطه دارید. و از prefetch_related زمانی استفاده میشه که شما چندین رابطه دارید. مثلا:
# Reduces database queries using select_related when accessing related objects
blogs = Blog.objects.select_related('author').all()
for blog in blogs:
print(blog.author)
# Retrieves related objects in separate queries using prefetch_related, improving performance
authors = Author.objects.prefetch_related('blogs').all()
for author in authors:
for blog in author.blogs.all():
print(post)
5. از n + 1 اجتناب کنید!
مشکل n + 1 زمانی اتفاق میوفته که شما میخواید مجموعه از آبجکت هارو بگیرید. مثلا فرض کنید مدل پست رو داریم. مدل پست n تا کامنت داره.
زمانی که شما میخواید تک تک کامنت هارو بگیرید و اطلاعاتش رو نشون بدید با n + 1 مواجه میشوید.
یک یعنی کوئری که برای گرفتن پست زده شده، و n تعداد کوئری هایی که برای گرفتن کامنت ها زده شده. از این قبیل مشکلات رو خیلی راحت میتونیم با select_related و prefetch_related برطرف کنیم و با یک کوئری اطلاعات تمامی کامنت هارو هم بگیریم(این رو هم در نظر بگیرید هر چقدر کامنت ها بیشتر باشه، کوئری که میزنیم سنگین تر میشه).
# Using prefetch_related to fetch related comments efficiently
blogs = Blog.objects.prefetch_related('comments').all()
for blog in blogs:
for comment in blog.comments.all():
print(comment)
link
#django #orm
@Syntax_fa
🔥11
Syntax | سینتکس
چند نکته طلایی موقعی که دارید از django orm استفاده می کنید. (قسمت اول) 1. کوئری ست هارو کاربردی بزنید: از filters و annotations و aggregation استفاده کنید تا فیلد هایی که نیاز دراید رو با کمترین سربار دریافت کنید. همچنین از متد defer و only برای محدود کردن…
چند نکته طلایی موقعی که داری از django orm استفاده می کنی.
(قسمت دوم)
6. افزایش پرفورمنس با استفاده از کش کردن.
کش کردن باعث میشه تعداد کوئری هایی که سمت دیتابیس میزنیم کاهش پیدا کنه. همچنین ریسپانس تایم دریافت اطلاعات خیلی کمتر بشه.
براش کش کردن می تونید از کش فریم ورک built-in جنگو استفاده کنید.
7. وقتی صحبت از آپدیت کردن و دیلیت کردن چندین row می شه، جنگو دو متد به اسم delete و update در اختیار ما قرار داده تا با پرفورمنس بهتر و سربار کمتر عملیات آپدیت و دیلیت کردن رو انجام بدیم.
8. بررسی و آنالیز کردن:
برای بررسی و دیباگ کردن، ابزار های زیادی در جنگو وجود دارد. مانند django debug toolbar. آنالیز کردن کوئری ها باعث میشه متوجه باتل نک ها شویم و بتونیم پرفومنس کوئری هارو افزایش بدیم.
9. از متد explain جنگو orm استفاده کن!!
همیشه از این متد استفاده کنید تا مطمئن شوید کوئری sql که orm برای شما ساخته است بهینه است و همان چیزی است که شما می خواهید.
10. عملیات هارو داخل دیتابیس انجام بده، نه توی زبان برنامه نویسی!!
کار های پایه رو میتونی با متد filter و exclude جنگو orm انجام بدی.
انجام یک سری عملیات ها روی فیلد هارو با F expression انجام بده
از annotation و aggregation استفاده کن
link
#django #orm
@Syntax_fa
(قسمت دوم)
6. افزایش پرفورمنس با استفاده از کش کردن.
کش کردن باعث میشه تعداد کوئری هایی که سمت دیتابیس میزنیم کاهش پیدا کنه. همچنین ریسپانس تایم دریافت اطلاعات خیلی کمتر بشه.
براش کش کردن می تونید از کش فریم ورک built-in جنگو استفاده کنید.
from django.core.cache import cache
# Retrieve posts from cache, if available
cached_posts = cache.get('all_posts')
if cached_posts is None:
cached_posts = list(Post.objects.all())
cache.set('all_posts', cached_posts)
7. وقتی صحبت از آپدیت کردن و دیلیت کردن چندین row می شه، جنگو دو متد به اسم delete و update در اختیار ما قرار داده تا با پرفورمنس بهتر و سربار کمتر عملیات آپدیت و دیلیت کردن رو انجام بدیم.
# Updating multiple posts' status in a single query
Blog.objects.filter(category='draft').update(status='published')
8. بررسی و آنالیز کردن:
برای بررسی و دیباگ کردن، ابزار های زیادی در جنگو وجود دارد. مانند django debug toolbar. آنالیز کردن کوئری ها باعث میشه متوجه باتل نک ها شویم و بتونیم پرفومنس کوئری هارو افزایش بدیم.
9. از متد explain جنگو orm استفاده کن!!
همیشه از این متد استفاده کنید تا مطمئن شوید کوئری sql که orm برای شما ساخته است بهینه است و همان چیزی است که شما می خواهید.
10. عملیات هارو داخل دیتابیس انجام بده، نه توی زبان برنامه نویسی!!
کار های پایه رو میتونی با متد filter و exclude جنگو orm انجام بدی.
انجام یک سری عملیات ها روی فیلد هارو با F expression انجام بده
از annotation و aggregation استفاده کن
link
#django #orm
@Syntax_fa
👍11
چرا باید از F expression توی django orm استفاده کنیم؟
در Django ORM، F expressions یا عبارات F، یک راه قدرتمند برای انجام عملیات روی فیلدهای مدل در سطح پایگاه داده هستند. با استفاده از عبارات F، میتوانید مقادیر فیلدها را در پایگاه داده بدون بازیابی و بروزرسانی در سطح کد Python تغییر دهید. این امر میتواند منجر به افزایش کارایی و جلوگیری از رخ دادن مشکلات race condition شود.
مثال کاربردی:
فرض کنید یک برنامه فروشگاه آنلاین دارید و میخواهید در هنگام خرید، تعداد موجودی کالا را کاهش دهید. میتوانید این کار را با استفاده از عبارات F در Django ORM به شکل زیر انجام دهید:
در این مثال، ما از
مزیت استفاده از عبارات F در این مثال این است که عملیات کاهش موجودی در سطح پایگاه داده انجام میشود، نه در سطح کد Python. این امر از بروز مشکلات race condition جلوگیری میکند، زیرا اگر چندین کاربر همزمان سعی در خرید یک محصول داشته باشند، عملیات کاهش موجودی به درستی انجام خواهد شد.
عبارات F همچنین میتوانند برای انجام عملیات پیچیدهتر روی فیلدهای مدل استفاده شوند. به عنوان مثال، میتوانید از آنها برای محاسبه درصد تخفیف و کاهش قیمت یک محصول استفاده کنید:
در این مثال، ما از عبارات F برای محاسبه قیمت جدید محصول با توجه به درصد تخفیف آن استفاده میکنیم.
عبارات F همچنین با عملگرهای انضمامی (annotated aggregates) و عملگرهای مقایسهای قابل استفاده هستند، که میتواند آنها را به ابزاری قدرتمند برای پردازش دادهها در سطح پایگاه داده تبدیل کند.
#django #orm
@Syntax_fa
در Django ORM، F expressions یا عبارات F، یک راه قدرتمند برای انجام عملیات روی فیلدهای مدل در سطح پایگاه داده هستند. با استفاده از عبارات F، میتوانید مقادیر فیلدها را در پایگاه داده بدون بازیابی و بروزرسانی در سطح کد Python تغییر دهید. این امر میتواند منجر به افزایش کارایی و جلوگیری از رخ دادن مشکلات race condition شود.
مثال کاربردی:
فرض کنید یک برنامه فروشگاه آنلاین دارید و میخواهید در هنگام خرید، تعداد موجودی کالا را کاهش دهید. میتوانید این کار را با استفاده از عبارات F در Django ORM به شکل زیر انجام دهید:
from django.db.models import F
# مدل Product
class Product(models.Model):
name = models.CharField(max_length=100)
stock = models.PositiveIntegerField()
# مثال خرید یک محصول
product = Product.objects.get(name='iPhone')
product.stock = F('stock') - 1
product.save()
در این مثال، ما از
F('stock')
استفاده میکنیم تا به Django بگوییم که مقدار فعلی فیلد stock
را از پایگاه داده بخواند. سپس، عملگر -
را به این مقدار اعمال میکنیم تا یک واحد از آن کم شود. در نهایت، با استفاده از `product.save()`، مقدار جدید را در پایگاه داده ذخیره میکنیم.مزیت استفاده از عبارات F در این مثال این است که عملیات کاهش موجودی در سطح پایگاه داده انجام میشود، نه در سطح کد Python. این امر از بروز مشکلات race condition جلوگیری میکند، زیرا اگر چندین کاربر همزمان سعی در خرید یک محصول داشته باشند، عملیات کاهش موجودی به درستی انجام خواهد شد.
عبارات F همچنین میتوانند برای انجام عملیات پیچیدهتر روی فیلدهای مدل استفاده شوند. به عنوان مثال، میتوانید از آنها برای محاسبه درصد تخفیف و کاهش قیمت یک محصول استفاده کنید:
from django.db.models import F
product.price = F('price') * (1 - F('discount_percent') / 100)
product.save()
در این مثال، ما از عبارات F برای محاسبه قیمت جدید محصول با توجه به درصد تخفیف آن استفاده میکنیم.
عبارات F همچنین با عملگرهای انضمامی (annotated aggregates) و عملگرهای مقایسهای قابل استفاده هستند، که میتواند آنها را به ابزاری قدرتمند برای پردازش دادهها در سطح پایگاه داده تبدیل کند.
#django #orm
@Syntax_fa
🔥12