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

Pav*_*rin 4 python django performance

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

providers = Provider.objects.filter(age__gt=10)
consumers = Consumer.objects.filter(consumer__in=providers)
Run Code Online (Sandbox Code Playgroud)

要么

providers_ids = Provider.objects.filter(age__gt=10).values_list('id', flat=True)
consumers = Consumer.objects.filter(consumer__in=providers_ids)
Run Code Online (Sandbox Code Playgroud)

Wil*_*uck 8

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

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

SELECT ... WHERE consumer.id IN (SELECT id FROM ... WHERE _ IN _)
Run Code Online (Sandbox Code Playgroud)

然而,你可以通过调用强制基于传递的主键明确值的查找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)
Run Code Online (Sandbox Code Playgroud)

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


kar*_*ikr 6

我同意Wilduck.然而几个笔记

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

consumers = Consumer.objects.filter(consumer__age__gt=10)
Run Code Online (Sandbox Code Playgroud)

这将为您提供相同的结果集 - 在单个查询中.

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

例:

print Provider.objects.filter(age__gt=10).query
Run Code Online (Sandbox Code Playgroud)

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