Django ORM values_list具有'__in'过滤性能

时间:2014-10-16 18:29:09

标签: python django performance

在Django中用'__in'过滤查询集的首选方法是什么?

providers = Provider.objects.filter(age__gt=10)
consumers = Consumer.objects.filter(consumer__in=providers)

providers_ids = Provider.objects.filter(age__gt=10).values_list('id', flat=True)
consumers = Consumer.objects.filter(consumer__in=providers_ids)

2 个答案:

答案 0 :(得分:8)

这些应该完全相同。在引擎盖下,Django会将这两者优化为SQL中的子选择查询。请参阅QuerySet API reference on in

此查询集将作为subselect语句进行评估:

SELECT ... WHERE consumer.id IN (SELECT id FROM ... WHERE _ IN _)

但是,您可以通过调用list上的values_list来强制执行基于传递主键显式值的查找,如下所示:

providers_ids = list(Provider.objects.filter(age__gt=10).values_list('id', flat=True))
consumers = Consumer.objects.filter(consumer__in=providers_ids)

在某些情况下,这可能会更高效,例如,当您的提供商很少时,它将完全取决于您的数据是什么以及您正在使用的数据库。请参阅上面链接中的“效果注意事项”说明。

答案 1 :(得分:6)

我同意Wilduck。然而几个笔记

您可以将这些过滤器组合成如下所示:

consumers = Consumer.objects.filter(consumer__age__gt=10)

这会在单个查询中为您提供相同的结果集。

第二件事,要分析生成的查询,最后可以使用.query子句。

示例:

print Provider.objects.filter(age__gt=10).query

将打印ORM将生成的查询以获取结果集。