Django: Какой самый быстрый способ заказать QuerySet на основе количества связанных полей? - PullRequest
1 голос
/ 17 августа 2011

В моем приложении Django есть модель Item с полем ManyToMany, которое обрабатывается с помощью промежуточной модели избранного. Вот упрощенные версии рассматриваемых моделей:

class Item(models.Model):
    name = models.CharField(max_length=200)

class Favorite(models.Model):
    user = models.ForeignKey(User)
    item = models.ForeignKey(Item)

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

items = Item.objects.annotate(num_favorites=Count('favorite')).order_by('-num_favorites')

Не уверен, относится ли это к каким-либо потенциальным ответам, но я разбиваю результаты на страницы, используя встроенный в Django Pagintor:

paginator = Paginator(items, 100)

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

Ниже приведен вывод функции MySQL EXPLAIN:

+----+-------------+--------------------+------+-----------------------------+-----------------------------+---------+-------------------------------+------+---------------------------------+
| id | select_type | table              | type | possible_keys               | key                         | key_len | ref                           | rows | Extra                           |
+----+-------------+--------------------+------+-----------------------------+-----------------------------+---------+-------------------------------+------+---------------------------------+
|  1 | SIMPLE      | appname_item       | ALL  | NULL                        | NULL                        | NULL    | NULL                          |  566 | Using temporary; Using filesort |
|  1 | SIMPLE      | appname_favorite   | ref  | appname_favorite_67b70d25   | appname_favorite_67b70d25   | 4       | appname.appname_item.id       |    1 |                                 |
+----+-------------+--------------------+------+-----------------------------+-----------------------------+---------+-------------------------------+------+---------------------------------+

Ответы [ 2 ]

1 голос
/ 17 августа 2011

когда вы пытаетесь использовать предложение order_by, индекс которого не определен, попробуйте задать для него индекс, это ускоряет процесс упорядочения, в вашем случае индекс для 'num_fabilities' - это то, что вам нужно для ускорения выполнения запросавремя.также техника, которую вы используете, хороша, в ней нет ничего плохого.

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

1 голос
/ 17 августа 2011

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

Панель отладки Django отлично подходит для диагностики подобных вещей - она ​​покажет вам, сколько времени занимает каждый запрос, и позволит вам запускать функцию db EXPLAIN для каждого из них.Документы MySQL сообщат вам, что означает вывод EXPLAIN.Однако после этого вам предстоит оптимизировать БД.

...