Django: Требуется много времени для фильтрации m2m-модели от m2m-связанной модели путем указания значений полей m2m-модели

Таблица m2m through имеет около 1,4 миллиона строк.

Замедление, вероятно, связано с большим количеством строк, но я уверен, что правильно пишу набор запросов. Как вы думаете, в чем причина?

Это займет около 400-1000 мс.

Если вы сделаете фильтр по pk вместо имени, это будет не так медленно.

# models.py
class Tag(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    name = models.CharField(unique=True, max_length=30)
    created_at = models.DateTimeField(default=timezone.now)


class Video(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    title = models.CharField(max_length=300)
    thumbnail_url = models.URLField(max_length=1000)
    preview_url = models.URLField(max_length=1000, blank=True, null=True)
    embed_url = models.URLField(max_length=1000)
    sources = models.ManyToManyField(Source)
    duration = models.CharField(max_length=6)
    tags = models.ManyToManyField(Tag, blank=True, db_index=True)
    views = models.PositiveIntegerField(default=0, db_index=True)
    is_public = models.BooleanField(default=True)
    published_at = models.DateTimeField(default=timezone.now, db_index=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
Video.objects.filter(tags__name='word').only('id').order_by('-published_at');

Запрос выдан

SELECT "videos_video"."id"
FROM "videos_video"
INNER JOIN "videos_video_tags" ON ("videos_video"."id" = "videos_video_tags"."video_id")
INNER JOIN "videos_tag" ON ("videos_video_tags"."tag_id" = "videos_tag"."id")
WHERE "videos_tag"."name" = 'word'
ORDER BY "videos_video"."published_at" DESC;

EXPLAIN(ANALYZE, VERBOSE, BUFFERS)

Я решил проблему, используя метод, описанный в комментарии Iain Shelvington.

Tag.objects.get(name='word').video_set.order_by('-published_at')

Есть ли в вашей базе данных именно такие индексы :

  1. "videos_tag" ("name", "id")
  2. "videos_video_tags" ("tag_id", "video_id")
  3. "videos_video" ("id", "published_at")

Если нет, попробуйте!

Вернуться на верх