TGViewer
Evo Dev Club Evo Dev Club @evodevclub · 629 subscribers
Post #356 1.31K

Forwarded from Євгеній Гизила

prefetch_related в Django

Недавно займався код-ревю Django проєктів і постійно бачив одну й ту ж проблему — N+1 запит. Для прикладу, ви робите один запит, щоб дістати 100 оголошень у вашому маркетплейсі, а потім ще 100 додаткових запитів, щоб дістати дані про магазин по кожному оголошенню. Сумарно у вас виходить 101 запит 😨: ваша база навантажена, клієнти довго очікують відповідь від сервера і ви прогріваєте повітря марною роботою.

В Django таку проблему легко може не помітити навіть досвідчений розробник, оскільки в Django ORM об’єкти є “розумними” і якщо ви дістаєте атрибут підв’язаної моделі, то Django зробить додатковий запит, щоб дістати підв’язану модель. Найлегше такі речі віднайти рев’юверу в циклах, де спочатку автор дістає список чогось з бази даних, а потім, обробляючи список у циклі, дістає підв’язану модель:

products = Product.objects.all()
for product in products:
print(product.shop.name)


Але є місця, де цикли заховані в самому Django і в такому випадку приходиться уважно передивлятися як отриманий список об’єктів обробляється до самого кінця запиту. На прикріпленому фото канонічний приклад такого захованого циклу.

Найлегше вирішити цю проблему, додавши .prefetch_related до запиту, який дістає список чогось (або .select_related, якщо ви розумієте різницю між цими методами). Метод .prefetch_related зробить додатковий запит і дістане всі підв’язані моделі одним запитом і покладе у внутрішній кеш. Унаслідок чого Django зробить два запити: один, щоб дістати оголошення, а один, щоб дістати магазини :

Products.objects \
.prefetch_related('shop') \
.all()

Щоб уникнути N+1 запиту в майбутньому, треба, в першу чергу, знати про таку проблему, можна спробувати тестувати кількість запитів або, найпростіше, при локальній розробці запускати базу в режимі логування всіх запитів і уважно слідкувати, щоб там не було сотні однотипних запитів.
  • 👍 18
  • 🔥 6
  • 😱 3
More from @evodevclub
  1. Dec 12, 2022🍠 GitLab написали довгий пост про те, як вони боролися з лейтенсі у Redis. https://about.…
  2. Aug 9, 2022⚙️ Лінк від нашого найкращого спеціаліста із Data Science Данила Петраківського Всі ж пам'…
  3. Aug 8, 2022Fwdays team продовжує підтримувати захисників та захисниць України 🇺🇦, до чого закликаєм…
  4. Jul 22, 2022🧑‍🏫 Projector створив платформу, на якій за донат можна поспілкуватися з менторами по рі…
  5. Jul 15, 2022🎙 Нарешті записали випуск WatEvoCast, цього разу без гостей. Говорили про прийдешній Pyth…
  6. Jul 12, 2022⛓ Наш колишній колега Андрій Бовсуновський, у своєму блозі розказує про свій погляд на роб…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →