代码之家  ›  专栏  ›  技术社区  ›  Tutunak

多表查询在Django中工作时间很长

  •  0
  • Tutunak  · 技术社区  · 7 年前

    我有一些型号:

    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\U链接的列表。 我编写了以下代码:

    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可以有许多标记,不同的标记可以有相同的标记发布。如果使用不带distinct的筛选器,我会得到许多重复项。
    Gif大约有18万个项目。

    标签上有大约70000个项目。

    TagToPublish大约有130个项目。

    每个Gif最多有30个标签。

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

    1 回复  |  直到 7 年前
        1
  •  0
  •   Aaron Klein    7 年前

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

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

    这将为您提供所有标记,其中包含一个要发布的标记。这样可以避免进行昂贵的表联接。类似地,上一个查询可以替换为

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

    这将再次避免表联接。照原样,当您只需要一个连接时,您的查询中就有三到四个连接,这可能是速度慢的原因。