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

更新字段或计数查询是“更好”的方法吗?

  •  0
  • imjoevasquez  · 技术社区  · 16 年前

    在我正在开发的一个django应用程序中,我发现了以下情况:

    class Parent(models.Model):
        name = models.CharField(...)
    
        def num_children(self):
            return Children.objects.filter(parent=self).count()
    
        def avg_child_rating(self):
            return Child.objects.filter(parent=self).aggregate(Avg('rating'))
    
    class Child(models.Model):
        name = models.CharField(...)
        parent = models.ForeignKey(Parent)
        rating = models.IntegerField(default=0)
    

    我计划进入 儿童平均评分 经常。会是 优化 如果我执行以下操作:

    class Parent(models.Model):
        ...
        num_children = models.IntegerField(default=0)
        avg_child_rating = models.FloatField(default=0.0)
    
    def update_parent_child_stats(sender, instance, **kwargs):
        num_children = Child.objects.filter(parent=instance.parent)
        if instance.parent.num_children != num_children:
            instance.parent.num_children = num_children
            instance.parent.avg_child_rating = Child.objects.filter(instance.parent=self).aggregate(Avg('rating'))
    
    post_save.connect(update_parent_child_stats, sender=Child)
    post_delete.connect(update_parent_child_stats, sender=Child)
    

    现在的区别是,每次创建/分级/删除子对象时,都会更新父对象。我知道创建/评级将经常进行。

    另外 昂贵的 ?

    1 回复  |  直到 16 年前
        1
  •  3
  •   rhettg    16 年前

    取决于问题的规模。 如果您预计会有大量的写流量,这可能是一个问题。与读(复制、缓存等)相比,扩展写要困难得多,也就是说,如果没有这个额外的查询,您可能会走很远的路,从而导致任何问题。

    根据您的统计信息的最新程度,您可以让其他进程(非Web会话)通过并每晚更新这些统计信息。