Django Generic Foreign keys - 考虑到SQL性能的好坏?

时间:2013-01-15 08:07:30

标签: django performance postgresql foreign-key-relationship

我有一个模型A,其中包含一个通用的外键关系,其中有3个其他模型的限制选择(将它们视为BCD)相同的应用。我知道通用外键的局限性,我们无法使用filterget或任何其他查询集操作。

为了达到这样的目的,A.objects.filter(generic_object__name="foo")我必须首先过滤B,C和D的对象作为查询集,迭代它们并使用通用反向关系将A对象作为列表(不是查询集。)

我不确定它会如何影响数据库上的SQL性能,因为查询不是直接的。

PS:我需要使用通用的外键,所以请建议任何SQL改进,而不是重新设计模型。

使用Django 1.4.3和Postgres。

4 个答案:

答案 0 :(得分:8)

我想引用David Cramer的一些话:Disqus的开发者,Django提交者

  

通用关系很好。它们并不慢,在代码库中管理起来更加困难。

我看到很多人告诉别人不使用通用关系,因为它很慢,但从不告诉它如何缓慢。

答案 1 :(得分:3)

Avoid Django's GenericForeignKey对通用外键中涉及的数据库设计反模式进行了详尽而详尽的描述(或者#34;多态关联,"因为他们称之为rails-speak)。

至于性能,每次要从模型中检索相关的GenericForeignKey资源时,它需要3个数据库查询:

  1. SELECT object_id_field,来自myapp_a的object_id WHERE id = 1;
  2. SELECT app_label,model FROM django_content_type WHERE id = A.object_type_field;
    • 在应用程序代码中,计算表名model + _ + app_label
  3. SELECT A.object_id_field FROM TABLE_NAME;
  4. 当人们说通用外键有性能损失时,他们会引用这个查询开销。

    在您真正想要使用通用外键的情况下,只有非常狭窄的情况。上面链接的文章也讨论了这些。

答案 2 :(得分:1)

为您的模型添加index_together Meta选项:

class Meta:
    index_together = [('cprofile_id', 'cprofile_type')]

答案 3 :(得分:0)

  

关于性能,每次您要从模型中检索相关的GenericForeignKey资源时,都要进行3个数据库查询

我不会完全同意。服务器启动后或在开发中更改文件后,仅执行一次数据库命中选择django_content_type的操作,然后将其缓存。因此,基本上只有2个数据库查询。