过滤器中的反向查找或对Django ORM中的pk的正向查找中哪个更快,更反向?

时间:2018-06-26 21:26:33

标签: python django django-queryset

我有一个看起来像这样的Django模型结构:

# Pre-defined User model

class A(models.Model):
    pass

class B(models.Model):
    relevant_users = models.ManyToManyField(User)
    related_A = models.ForeignKey(A)

给定一个User,我想快速生成一个查询集,其中包含用户在relevant_users多对多情况下与B相连的所有A。我希望有很多A,但是每个A只有一个或两个B,并且仅对pk进行索引。

我有两种方法来生成此查询集,并且都可以工作:

方法1: 使用反向查找过滤A对象。

queryset = A.objects.filter(B__relevant_users__exact=user)

方法2: 使用正向查找获取A pk的列表,然后在A表中找到这些pk。 (使用的是select_related,为清楚起见,在此省略)

a_pks = [b.related_A.pk for b in user.b_set.all()]
queryset = A.objects.filter(pk__in=a_pks)

这些等效吗?对于大量的A,它们是否具有相同的时间复杂度?

编辑:在某些情况下,方法2看起来更快:

针对人口稀少的relevant_users(大多数为空白):

A:10,000 m1:0.0014s 平方米:0.0024秒

A:100,000 m1:0.0016秒 平方米:0.0028秒

对于人口稠密的relevant_users(所有B都有至少一个用户):

A:10,000 m1:0.040秒 平方米:0.019秒

A:20,000 m1:0.066秒 平方米:0.031秒

1 个答案:

答案 0 :(得分:1)

方法2与数据库进行两次往返,因此自然比方法1(仅进行一次往返)慢近两倍。当您只能执行一个查询时,请避免进行两个查询,除非一个查询需要过于复杂的聚合,有时有时可以在python的客户端上更快地进行聚合。