Django ORM 使用 '__in' 过滤器的性能

5 投票
2 回答
3605 浏览
提问于 2025-04-28 00:05

在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)

在某些情况下,这样做可能会更高效,比如当你有少量提供者时,但具体效果还是要看你的数据是什么样的,以及你使用的数据库是什么。可以查看上面链接中的“性能考虑”部分。

撰写回答