我有一个模型A
,其中包含一个通用的外键关系,其中有3个其他模型的限制选择(将它们视为B
,C
和D
)相同的应用。我知道通用外键的局限性,我们无法使用filter
或get
或任何其他查询集操作。
为了达到这样的目的,A.objects.filter(generic_object__name="foo")
我必须首先过滤B,C和D的对象作为查询集,迭代它们并使用通用反向关系将A
对象作为列表(不是查询集。)
我不确定它会如何影响数据库上的SQL性能,因为查询不是直接的。
PS:我需要使用通用的外键,所以请建议任何SQL改进,而不是重新设计模型。
使用Django 1.4.3和Postgres。
答案 0 :(得分:8)
我想引用David Cramer的一些话:Disqus的开发者,Django提交者
通用关系很好。它们并不慢,在代码库中管理起来更加困难。
我看到很多人告诉别人不使用通用关系,因为它很慢,但从不告诉它如何缓慢。
答案 1 :(得分:3)
Avoid Django's GenericForeignKey对通用外键中涉及的数据库设计反模式进行了详尽而详尽的描述(或者#34;多态关联,"因为他们称之为rails-speak)。
至于性能,每次要从模型中检索相关的GenericForeignKey资源时,它需要3个数据库查询:
model + _ + app_label
TABLE_NAME
; 当人们说通用外键有性能损失时,他们会引用这个查询开销。
在您真正想要使用通用外键的情况下,只有非常狭窄的情况。上面链接的文章也讨论了这些。
答案 2 :(得分:1)
为您的模型添加index_together Meta选项:
class Meta:
index_together = [('cprofile_id', 'cprofile_type')]
答案 3 :(得分:0)
关于性能,每次您要从模型中检索相关的GenericForeignKey资源时,都要进行3个数据库查询
我不会完全同意。服务器启动后或在开发中更改文件后,仅执行一次数据库命中选择django_content_type的操作,然后将其缓存。因此,基本上只有2个数据库查询。