Django ORM: Оптимизация запросов, включающих many-many отношения

Это зависит от того, как свойство используется. Например, скажите, что у Вас есть студенческий объект, который имеет свойство имени. Вы могли использовать Ваш Заставлять метод вытягивать имя от базы данных, если это уже не было получено. Таким образом, Вы уменьшаете ненужные вызовы до базы данных.

Теперь скажем, у Вас есть частный целочисленный счетчик в Вашем объекте, который считает количество раз, которым назвали имя. Можно хотеть не использовать Получить метод из объекта, потому что это произвело бы недопустимое количество.

5
задан shylent 29 October 2009 в 07:22
поделиться

3 ответа

Думаю, вы уже обозначили две простые возможности. Либо вы выполняете один запрос с фильтром для Generic, а затем приводите каждый элемент к его конкретному подтипу (в результате получается n + 1 запросов, где n - количество возвращенных элементов), либо вы выполняете отдельный запрос для каждой конкретной таблицы (приводит к k запросов, где k - количество конкретных типов).

На самом деле стоит провести сравнительный анализ, чтобы увидеть, какой из них в действительности быстрее. Второй вариант кажется лучше, потому что в нем (вероятно) меньше запросов, но каждый из этих запросов должен выполнять соединение с промежуточной таблицей m2m. В первом случае вы выполняете только один запрос на соединение, а затем много простых. Некоторые бэкэнды базы данных лучше работают с большим количеством небольших запросов, чем с меньшим количеством более сложных запросов.

Если второй действительно значительно быстрее для вашего варианта использования, и вы готовы проделать дополнительную работу по очистке вашего кода, он должен можно написать собственный метод менеджера для общей модели, который «предварительно выбирает» все данные подтипа из соответствующих конкретных таблиц для данного набора запросов, используя только один запрос на таблицу подтипа; аналогично тому, как этот фрагмент оптимизирует общие внешние ключи с помощью массовой предварительной выборки. Это даст вам те же запросы, что и ваш второй вариант, с синтаксисом DRYer вашего первого варианта.

Если вы хотите проделать дополнительную работу по очистке вашего кода, должна быть возможность написать собственный метод менеджера для общей модели, который «предварительно выбирает» все данные подтипа из соответствующих конкретных таблиц для данного набора запросов, используя только один запрос по таблице подтипов; аналогично тому, как этот фрагмент оптимизирует общие внешние ключи с помощью массовой предварительной выборки. Это даст вам те же запросы, что и ваш второй вариант, с синтаксисом DRYer вашего первого варианта.

Если вы хотите проделать дополнительную работу по очистке вашего кода, должна быть возможность написать собственный метод менеджера для общей модели, который «предварительно выбирает» все данные подтипа из соответствующих конкретных таблиц для данного набора запросов, используя только один запрос по таблице подтипов; аналогично тому, как этот фрагмент оптимизирует общие внешние ключи с помощью массовой предварительной выборки. Это даст вам те же запросы, что и ваш второй вариант, с синтаксисом DRYer вашего первого варианта.

2
ответ дан 15 December 2019 в 06:29
поделиться

Not a complete answer but you can avoid a great number of hits by doing this

items= list(items)
for item in items:
    spec = getattr(item, item.get_my_specific_type())

instead of this :

for item in items:
    spec = getattr(item, item.get_my_specific_type())

Indeed, by forcing a cast to a python list, you force the django orm to load all elements in your queryset. It then does this in one query.

1
ответ дан 15 December 2019 в 06:29
поделиться

Я случайно наткнулся на следующее сообщение, которое в значительной степени отвечает на ваш вопрос:

http://lazypython.blogspot.com/2008/11 /timeline-view-in-django.html[1270pting

0
ответ дан 15 December 2019 в 06:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: