使用prefetch_related进行Django查询集优化

时间:2018-01-11 03:32:00

标签: python django

我正在开发一个基于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()

Model Relation

我想检索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)

这可能吗?如果是这样,怎么样?感谢。

(或者我可以将BC组合成一个模型,方法是引入一个字段来表示类型(B或C),现在B和C的两个非共享字段都是共享的,但我认为这是对存储的浪费,因为bar2对B没有任何意义,bar1对C表示没有任何意义。

0 个答案:

没有答案