Django N + 1 решение для запросов - PullRequest
13 голосов
/ 24 марта 2011

Я посетил http://guides.rubyonrails.org/active_record_querying.html после разговора с пэром относительно N + 1 и серьезных последствий для производительности плохих запросов к БД.

ActiveRecord (Rails):

clients = Client.includes(:address).limit(10)

Там, где у клиентов есть адреса, и я намереваюсь получить к ним доступ во время циклического обхода клиентов, Rails предоставляет includes, чтобы сообщить об этом и добавить их в запрос, что сразу исключает 9 запросов.

Django:

https://github.com/lilspikey/django-batch-select обеспечивает поддержку пакетных запросов.Знаете ли вы о других библиотеках или приемах для достижения того, что Rails предоставляет выше, но в менее многословном поместье (как в примере с rails, где только 19 символов исправляют N + 1 и это очень ясно)?Кроме того, пакетный выбор решает проблему одинаково, или это две разные вещи?

Кстати, я не спрашиваю о select_related, хотя на первый взгляд это может показаться ответом,Я говорю о ситуации, когда у address есть внешний ключ к client.

Ответы [ 3 ]

12 голосов
/ 21 января 2013

Вы можете сделать это с prefetch_related начиная с Django 1.4: https://docs.djangoproject.com/en/dev/ref/models/querysets/#prefetch-related

Если вы используете <1.4, взгляните на этот модуль: <a href="https://github.com/ionelmc/django-prefetch">https://github.com/ionelmc/django-prefetch

Он утверждает, что он более гибок, чем prefetch_related в Django. Многословно, но прекрасно работает.

9 голосов
/ 24 марта 2011

К сожалению, ORM в Django до сих пор не имеет возможности сделать это.

К счастью, это возможно сделать всего за 2 запроса, при этом немного работы в Python.

clients = list(Client.objects.all()[:10])
addresses = dict((x.client_id, x) for x in
    Address.objects.filter(client__in=clients))
for client in clients:
  print client, addresses[client.id]
2 голосов
/ 11 ноября 2011

django-batch-select должен дать ответ на эту проблему, хотя я не пробовал его.Ответ Игнасио выше кажется мне лучшим.

...