Запрос Django ORM, чтобы найти все объекты, которые не имеют недавнего связанного объекта - PullRequest
1 голос
/ 10 ноября 2011

У меня есть повторяющийся шаблон в моем коде, где модель имеет связанную модель (один ко многим), которая отслеживает ее историю / статус.Эта связанная модель может иметь много объектов, представляющих моментальный снимок состояния модели.

Например:

class Profile(models.Model):
    pass

class Subscription(models.Model):
    profile = models.ForeignKey(Profile)
    data_point = models.IntegerField()
    created = models.DateTimeField(default=datetime.datetime)

#Example objects
p = Provile()
subscription1 = Subscription(profile=p, data_point=32, created=datetime.datetime(2011, 7 1)
subscription2 = Subscription(profile=p, data_point=2, created=datetime.datetime(2011, 8 1)
subscription3 = Subscription(profile=p, data_point=3, created=datetime.datetime(2011, 9 1)
subscription4 = Subscription(profile=p, data_point=302, created=datetime.datetime(2011, 10 1)

Мне часто приходится запрашивать эти модели, чтобы найти всеОбъекты «Профиль», которые не обновлялись по подписке в течение последних 3 дней или аналогичные.Для этого я использовал запросы на выборку:

q = Subscription.objects.filter(created__gt=datetime.datetime.now()-datetime.timedelta(days=3).values('id').query
Profile.objects.exclude(subscription__id__in=q).distinct()

Проблема в том, что это очень медленно, когда задействованы большие таблицы.Есть ли более эффективный шаблон для такого запроса?Может быть, какой-нибудь способ заставить Django использовать JOIN вместо SUBSELECT (похоже, поможет избавиться от всех этих внутренних вложенных циклов)?

Мне бы хотелось использовать ORM, но при необходимости я быготов использовать метод .extra () или даже необработанный SQL, если повышение производительности достаточно убедительно.

Я работаю с Django 1.4alpha (SVN Trunk) и Postgres 9.1.

Ответы [ 2 ]

0 голосов
/ 18 февраля 2016

Добавление индекса БД к created:

created = models.DateTimeField(default=datetime.datetime, db_index=True)

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

Запросы с использованием столбцов БД без индексов выполняются очень быстро.Если вы хотите более подробно проанализировать узкие места в запросах, включите ведение журнала для более длинных операторов (например, 200 мс и выше) и выполните explain analyze (postgres) для длительных запросов.

РЕДАКТИРОВАТЬ: IВы только что увидели в своем комментарии, что у вас есть индекс на поле.В этом случае все больше причин смотреть на вывод explain analyze.

  1. , чтобы убедиться, что индекс действительно используется, и в полном объеме.
  2. дляпосмотрите, не излишне ли postgres пишет на диск вместо использования памяти

См. - при планировании запроса http://www.postgresql.org/docs/current/static/runtime-config-query.html

Может быть, это поможет в качестве вступления: http://blog.it -agenten.com / 2015/11 / тюнинг-Джанго-ОРМ-часть-2-многие-ко-многим-запросов /

0 голосов
/ 10 ноября 2011
from django.db.models import Max
from datetime import datetime, timedelta

Profile.objects.annotate(last_update=Max('subscription__created')).filter(last_update__lt=datetime.now()-timedelta(days=3))

Агрегация (и аннотация) - потрясающий соус, см .: https://docs.djangoproject.com/en/dev/topics/db/aggregation/

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