在我正在研究的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)
我打算经常访问 avg_child_rating 。如果我执行以下操作,它会优化:
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)
现在的不同之处在于,每次创建/评级/删除子项时,都会更新Parent对象。我知道创建/评级会经常完成。
还有什么昂贵的?
答案 0 :(得分:3)
取决于问题的严重程度。 如果您预计会有大量写入流量,这可能是一个问题。缩放写入比读取(复制,缓存等)要困难得多。也就是说,如果没有这些额外的查询可能会导致任何问题,您可能会走很长的路。
根据您的统计信息的最新状态,您可以通过其他进程(非网络会话)来完成并每晚更新这些统计信息。