我正在开发一个基于Django 1.11的项目,我正在尝试使用prefetch_related
优化数据库访问,这是我面临的问题:
我有一些模型定义(简化):
class D(models.Model):
foo = models.IntegerField()
class A(models.Model):
foo = models.FloatField()
class B(models.Model):
a = models.ForeignKey(A)
d = models.ForeignKey(D, related_name='bs')
# Some fields are identical to C
foo = models.CharField()
# A special field
bar1 = models.FileField()
class C(models.Model):
a = models.ForeignKey(A)
d = models.ForeignKey(D, related_name='cs')
# Some fields are identical to B
foo = models.CharField()
# A special field
bar2 = models.FloatField()
我想检索D
的一些对象,当从DB中检索它们时,我想要检索它们以及所有相关的(直接)B
对象和C
对象及相关(间接的A
个对象,目前我正在使用:
>>> qs = D.objects.filter(foo=1) # some queryset of D
>>> qs = qs.prefetch_related('bs__a', 'cs__a')
性能还可以(与没有prefetch_related
相比),我看到来自django-debug-toolbar
的原始SQL查询,看起来像Django将查询分解为类似(伪装SQL):
select * from D
select * from B where `d`.`id` in (ids from D)
select * from A where `A`.`id` in (ids from B) ---> first time
select * from C where `d`.`id` in (ids from D)
select * from A where `A`.`id` in (ids from C) ---> second time
但我想要的是,来自B和C的Concat ID并导致一个查询到A:
select * from D
select * from B where `d`.`id` in (ids from D)
select * from C where `d`.`id` in (ids from D)
select * from A where `A`.`id` in (ids from B, ids from C)
这可能吗?如果是这样,怎么样?感谢。
(或者我可以将B
和C
组合成一个模型,方法是引入一个字段来表示类型(B或C),现在B和C的两个非共享字段都是共享的,但我认为这是对存储的浪费,因为bar2对B没有任何意义,bar1对C表示没有任何意义。