<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>نوشته های Amin A2</title><link>https://virgool.ir/feed/@AminA2</link><description></description><language>fa</language><pubDate>2026-11-11 15:17:46</pubDate><image><url>https://files.virgool.ir/upload/users/5281/avatar/3lfPc6.png</url><title>Amin A2</title><link>https://virgool.ir/@AminA2</link></image><item><title>بهینه سازی دسترسی به دیتابیس در جنگو</title><link>https://virgool.ir/Rycaco/بهینه-سازی-دسترسی-به-دیتابیس-در-جنگو-قسمت-اول-upuuu3nucxws</link><description>یه مدت میشه که جنگو رو شروع کردم و از این به بعد اینجا قراره از تجربیاتم بنویسم.خب، بریم که شروع کنیم.حل مشکلN+1 کوئری در جنگویکی از اولین مشکلاتی که هنگام کار کردن با دیتای واقعی بهش برمی‏خورید مسئلهN+1 کوئریه. میگم دیتای واقعی چون وقتی رکوردهای یک جدول زیاد بشه و زمان پاسخ سرور بالا بره تازه متوجه میشید که یه جای کار میلنگه. اینجا سعی شده با یک مثال ساده، اصل مسئله و راه حلش توضیح داده بشه.                 فرض کنید این مدل‏ها رو داریم:class Author(models.Model):&#xA;        name = models.CharField(max_length=30)class Book(models.Model):&#xA;        name = models.CharField(max_length=50)&#xA;        author = models.ForeignKey(Author, on_delete=’models.Cascade’, related_name=books)حالا می‏خوایم یک کتاب با id مشخص رو بگیریم و نام نویسنده ‏اش رو بیرون بکشیم:book = Book.objects.get(pk=1)&#xA;book.author.nameاینجا یک کوئری برای خط اول و select کردن کتاب و یه کوئری دیگه برای خط دوم و گرفتن نام نویسنده کتاب اجرا میشه.تا اینجا به نظر نمیاد مشکل خاصی وجود داشته باشه.جایی به مشکل برمی‏خوریم که تعداد زیادی کتاب هست و میخوایم لیستی از نام کتاب به همراه نام نویسنده کتاب داشته باشیم.output = []&#xA;for book in Book.objects.all():&#xA;        output.append({&#xA;        ‘book’: book.name,&#xA;        ‘author’: book.author.name&#xA;        })یکبار همه کتاب‏ها رو select می‏ کنیم و بعدش برای هر کتاب نام نویسنده ‏اش رو می گیریم. هربار دسترسی به کلید خارجی نیاز به یک کوئری داره و اینجا ما به تعداد کتاب‏ ها کوئری خواهیم داشت به علاوه کوئری اول که همه کتاب‏ ها رو گرفتیم. N+1 از اینجا میاد.هر چه تعداد کتاب ها بالاتر بره تعداد کوئری ‏ها بیشتر میشه و سرعت بیرون کشیدن اطلاعات کم و کمتر.دلیل این اتفاق هم این هست که در جنگو اساساً Querysetها Lazy هستند و تا وقتی نیاز به اونها نباشه، اجرا نمیشن. در اینجا هم وقتی select روی کتاب ‏ها اتفاق میوفته، آبجت‏های مرتبط (related_object) مثل نویسنده کتاب لود نمیشه. درست وقتی که نام نویسنده رو میخوایم کوئری مربوط به اون اجرا میشه.در مقابل این مفهوم، Eager loading رو داریم. در Eager loading تمام داده‏های مورد نیاز بصورت یکجا لود میشن و بنابراین فقط یک کوئری کافیه تا نام کتاب ‏ها و نویسندها‏شون رو داشته باشیم.در جنگو از طریق تابع select_related میتونیم Eager loading رو پیاده کنیم:for book in Book.objects.all().select_related(‘author’):&#xA;        output.append({&#xA;        ‘book’: book.name,&#xA;        ‘author’: book.author.name&#xA;        })این select_related درواقع یک Join در SQL هست که برای ارتباطات یک به یک و یک به چند کاربرد داره.تابع دیگری به اسم prefetched_related وجود داره که همین Join رو نه در SQL که در پایتون انجام میده و برای روابط یک به چند و چند به چند استفاده میشه.</description><category>Amin A2</category><author>Amin A2</author><pubDate>Sat, 31 Jul 2021 01:15:12 +0430</pubDate></item></channel></rss>