Django ORM 使用 '__in' 过滤器的性能
在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 个回答
6
我同意Wilduck的看法。不过有几点需要说明。
你可以把这些过滤条件合并成一个,像这样:
consumers = Consumer.objects.filter(consumer__age__gt=10)
这样做会让你在一次查询中得到相同的结果。
第二点是,要分析生成的查询,你可以在最后加上.query
这个部分。
举个例子:
print Provider.objects.filter(age__gt=10).query
这样会打印出ORM生成的查询,用来获取结果集。
10
这两种写法应该是完全一样的。在后台,Django 会把这两种写法都优化成 SQL 的子查询。你可以查看 关于 in
的 QuerySet API 参考。
这个查询集会被处理成子查询语句:
SELECT ... WHERE consumer.id IN (SELECT id FROM ... WHERE _ IN _)
不过,你可以通过在 values_list
上调用 list
来强制进行基于主键的查找,像这样:
providers_ids = list(Provider.objects.filter(age__gt=10).values_list('id', flat=True))
consumers = Consumer.objects.filter(consumer__in=providers_ids)
在某些情况下,这样做可能会更高效,比如当你有少量提供者时,但具体效果还是要看你的数据是什么样的,以及你使用的数据库是什么。可以查看上面链接中的“性能考虑”部分。