Нужна помощь в оптимизации этого агрегатного запроса Django - PullRequest
0 голосов
/ 07 июня 2010

У меня есть следующая модель

class Plugin(models.Model):
    name = models.CharField(max_length=50)
    # more fields

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

class Download(models.Model):
    plugin = models.ForiegnKey(Plugin)
    timestamp = models.DateTimeField(auto_now=True)

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

# pbd is plugins by download - commented here to prevent scrolling
pbd = Plugin.objects.annotate(dl_total=Count('download')).order_by('-dl_total')

, который работает, но очень медленно.Только с 1000 плагинов, в среднем.ответ составляет 3,6 - 3,9 секунды (devserver с локальной базой данных PostgreSQL), где аналогичное представление с гораздо более простым запросом (сортировка по дате выпуска плагина) занимает около 160 мс.

Я ищу предложения о том, какоптимизировать этот запрос.Я бы действительно предпочел, чтобы запрос возвращал Plugin объектов (в отличие от использования values), так как я делюсь тем же шаблоном для других представлений (Плагины по рейтингу, Плагины по дате выпуска и т. Д.), Поэтомушаблон ожидает Plugin объектов - плюс я не уверен, как бы получить такие вещи, как absolute_url без ссылки на объект плагина.

Или весь мой подход обречен на провал?Есть ли лучший способ отслеживать загрузки?В конечном итоге я хочу предоставить пользователям некоторую хорошую статистику загрузки для загружаемых плагинов - например, загрузок за день / неделю / месяц.Придется ли мне рассчитывать и кэшировать загрузки в какой-то момент?

РЕДАКТИРОВАТЬ: в моем тестовом наборе данных есть где-то между 10-20 экземплярами загрузок на плагин - в производстве я ожидаю, что это число будет намного выше для многихплагины.

Ответы [ 2 ]

0 голосов
/ 07 июня 2010

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

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

0 голосов
/ 07 июня 2010

Аннотации явно медленные, так как они должны обновлять каждую запись в БД.

Одним из прямых способов является денормализация поля БД. Используйте поле download_count на моделях плагинов, которое увеличивается при новом сохранении Download. Используйте сортировку по совокупному запросу на плагинах.

Если вы думаете, что будет слишком много загрузок, чтобы постоянно обновлять другую запись плагина, вы можете обновить поле download_count на плагине через cron.

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