14

我有一个模型,它包含一个通用外键关系,并在同一个应用程序中A限制了对 3 个其他模型的选择(将它们视为和)。而且我知道我们不能使用或任何其他查询集操作的通用外键的局限性。BCDfilterget

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

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

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

使用 Django 1.4.3 和 Postgres。

4

3 回答 3

17

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

类属关系很好。它们并不慢,只是在您的代码库中更难管理。

我看到很多人告诉其他人不要使用泛型关系,因为它很慢,但从不告诉它有多慢。

于 2013-01-15T09:18:06.727 回答
14

避免 Django 的 GenericForeignKey对涉及通用外键(或“多态关联”,他们在 rails-speak 中称它们)中涉及的数据库设计反模式有一个很好而全面的描述。

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

  1. SELECT object_id_field, object_id from myapp_a WHERE id=1;
  2. 选择 app_label,模型 FROM django_content_type WHERE id=A.object_type_field;
    • 在应用程序代码中,计算表名model + _ + app_label
  3. 选择 A.object_id_field FROM TABLE_NAME;

当人们说通用外键有性能损失时,他们指的是这个查询开销。

只有极少数情况下您真正想要使用通用外键。上面链接的文章也讨论了这些。

于 2017-12-31T23:11:00.790 回答
3

向模型添加 index_together Meta 选项:

class Meta:
    index_together = [('cprofile_id', 'cprofile_type')]
于 2016-09-28T15:14:10.727 回答