Как оптимизировать select_related с выбором лимита / смещения? - PullRequest
0 голосов
/ 26 января 2012

Пример:

# consider the following query run in a loop
q = Users.objects.all().select_related('profile', 'address')[start:start+batchsize]

# assume start == 1,000,000 and batchsize == 1000
print q.query

SELECT ... LEFT OUTER JOIN profile ... LIMIT 1000 OFFSET 1000000;

Проблема:

Использование здесь select_related ускоряет мой запрос, потому что в противном случае django будет делать дополнительные вызовы БД для получения профиля / адреса (и многих других таблиц), когда я получу к ним доступ позже в цикле. Однако, хотя это ускоряет начало итераций, когда значение OFFSET велико, оно на самом деле замедляется.

1) Кто-нибудь еще сталкивался с этой проблемой? 2) Есть ли обходной путь в django для решения этой проблемы?

Я подозреваю, что это проблема с механизмом запросов MySQL, но просто хочу знать, могу ли я структурировать свой код django, чтобы, возможно, помочь оптимизатору запросов в MySQL.

Спасибо

1 Ответ

1 голос
/ 27 января 2012

Здесь нет ничего действительно "обходного пути". Это ожидаемое поведение. select_related выполняет SQL-JOIN для каждого внешнего ключа, который вы передаете. Это по своей сути более сложный запрос для базы данных для обработки. Чем больше строк в ваших таблицах, тем дольше это займет.

Действительно, все, что вы можете сделать в этом сценарии, это применить как можно больше оптимизации к вашему столу. Если столбцы profile_id и address_id еще не проиндексированы, вы должны добавить для них индексы (но у меня есть подозрение, что Django уже сделал это для вас.

Если вам не нужны все поля, вы можете попробовать отправить более ограниченный запрос (требующий меньше сетевой работы), используя .values() или .values_list(). Вы даже можете указать поля для profile и address.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...