使用许多表的查询在Django中工作很长时间

时间:2018-01-20 17:44:25

标签: python django django-queryset

我有一些模特:

class TagToPublish(models.Model):
    tag_to_publish = models.TextField()
    ru_tag = models.TextField(blank=True)
    eng_tag = models.TextField(blank=True)

    def __str__(self):
        return self.tag_to_publish


class Tag(models.Model):
    tag = models.TextField(unique=True)
    active = models.BooleanField(default=False)
    tag_to_publish = models.ForeignKey(TagToPublish, blank=True, null=True, on_delete=models.SET_NULL)
    not_to_publish = models.BooleanField(default=False)

    def __str__(self):
        return self.tag

    def count(self):
        return self.gif_set.count()


class Gif(models.Model):
    link = models.URLField(unique=True)
    # link = models.ImageField()
    post = models.ForeignKey(Post)
    tagged = models.ManyToManyField(Tag)
    to_publish = models.BooleanField(default=False)
    never_publish = models.BooleanField(default=False)
    choices = models.IntegerField(
        choices=[
            (1, 'To publish'),
            (2, 'Never Publish'),
            (0, 'Null')
            ], default=0)

    def image(self):
        return '<image src={} />'.format(self.link)

    image.allow_tags = True

    def __str__(self):
        return self.link

    def tag_to_publish(self):
        for tag in self.tagged.all():
            tag_to_publish = tag.tag_to_publish
            if tag_to_publish:
                return tag_to_publish


class Order(models.Model):
    order_name = models.TextField(blank=True)


class InOrder(models.Model):
    order = models.ForeignKey(Order)
    gif = models.ForeignKey(Gif)
    place_in_order = models.IntegerField(blank=True)
    published = models.BooleanField(default=False)

我希望获得一个包含要发布标记的唯一gif_links的列表。 我写了这段代码:

tags = TagToPublish.objects.all()
tags_to_publish = Tag.objects.filter(tag_to_publish__in=tags)
gif_set = Gif.objects.filter(tagged__tag_to_publish__tag__in=tags_to_publish).distinct()[:100]   

但它的工作时间很长,因为每个Gif可以有很多标签,不同的标签可以有相同的TagToPublish。如果使用过滤器没有明显我有很多重复 Gif有大约18万件物品。

标签有大约70 000个项目。

TagToPublish有大约130个项目。

每个Gif最多有30个标签。

我该如何解决这个问题?对于100个独特的项目,需要30秒,100%加载两个CPU核心。

1 个答案:

答案 0 :(得分:0)

您的第一个查询可以删除,第二个查询替换为

tags_to_publish = Tag.objects.filter(tag_to_publish__is_null=False)

将为您提供所有带标签的标签。这使您无需进行昂贵的表连接。同样,您的上一个查询可以替换为

gif_set = Gif.objects.filter(tagged__in=tags_to_publish).distinct()[:100]

这将再次使您免于表连接。当你只需要一个连接时,你的查询中有三个或四个连接,这可能是缓慢的来源。