Python Django:.filter(key\uu in=set)和.filter(key\uu in=list)之间的性能有差异吗

Python Django:.filter(key\uu in=set)和.filter(key\uu in=list)之间的性能有差异吗,python,django,Python,Django,我是在我已经有一个列表的情况下问这个问题的,我想知道是否值得将其转换为一个集合以用于筛选查询,即哪一个更好: some_set=set(some_列表) some\u qs=SomeModel.objects.filter(some\u key\u in=some\u set) vs some\u qs=SomeModel.objects.filter(some\u key\u in=some\u list) 我知道,如果您想从另一个列表b中的列表a中查找元素,通常值得将列表b转换为一个集合

我是在我已经有一个列表的情况下问这个问题的,我想知道是否值得将其转换为一个集合以用于筛选查询,即哪一个更好:

some_set=set(some_列表)
some\u qs=SomeModel.objects.filter(some\u key\u in=some\u set)
vs

some\u qs=SomeModel.objects.filter(some\u key\u in=some\u list)

我知道,如果您想从另一个列表
b
中的列表
a
中查找元素,通常值得将列表
b
转换为一个集合,因为列表中的
x
是O(n),集合中的
x
是O(1)。但是我不知道Django是如何在中实现查询过滤器的,所以我不确定在这种情况下哪个选项更好。

如果有疑问,可以打印
my\u query.explain()
,查看这两个选项之间是否有任何差异。在您的情况下,这是非常不可能的,因为set中的
x确实发生在SQL端,而不是python端,django将在将iterable发送到SQL之前将其转换为字符串。

这可能是特定于DB系统的,所以首先我应该提到我使用的是PostgreSQL

按照blue_note的建议,我用
.explain()
查看了查询执行计划,对于每个项目重复4次的列表和具有相同项目的集合,它是相同的(除了项目顺序)。这意味着Django在内部执行某种列表来设置转换。接下来,我使用
timeit
查看这两种方法中的哪一种更快,结果表明,首先将列表转换为集合更快。这是我的密码:

从timeit导入timeit
qs=SomeModel.objects.all()
l=[str(x.id)表示qs中的x]
l、 延长(l)
l、 延长(l)
def t_l():
返回SomeModel.objects.filter(id\uu in=l)
def t_s():
返回SomeModel.objects.filter(id\uu in=set(l))
>>>SomeModel.objects.filter(id\uu in=l.explain())
“身份验证时位图堆扫描\u permissionsvatnumber(成本=9.26..19.48行=8宽度=86)\n重新检查条件:(id=任意('4)B 7-7 7-7 7-18 18-18 18-18-7 7-7 7-7 7-7 7-7 7-7 7-7 7-18-18-18-18-18-18-18-18-18-18-7 7-7 7 7-7 7-7 7 7-7 7-8 8 8 8 8-4-7 7 7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7 7 7 7-7-7-7 7 7 7 7 7-7 7 7 7 7-7 7-7 7 7-8 8 8 8 8 8-18-18-18-18-18-18-18-18-18 18 18 18-18 18-18-18-18 18 18 18 18 18 18 18 18 18-18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 a}'::uuid[]))\n->身份验证时位图索引扫描\u permissionsvatnumber\u pkey(成本=0.00..9.26行=8宽度=0)\n索引条件:(id=ANY('4)B 7-7 7-7 7-18 18-18 18-18-7 7-7 7-7 7-7 7-7 7-7 7-7 7-18-18-18-18-18-18-18-18-18-18-7 7-7 7 7-7 7-7 7 7-7 7-8 8 8 8 8-4-7 7 7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7-7 7 7 7-7-7-7 7 7 7 7 7-7 7 7 7 7-7 7-7 7 7-8 8 8 8 8 8-18-18-18-18-18-18-18-18-18 18 18 18-18 18-18-18-18 18 18 18 18 18 18 18 18 18-18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 a}'::uuid[])”
>>>SomeModel.objects.filter(id\uu in=set(l)).explain()
“身份验证时位图堆扫描\u permissionsvatnumber(成本=9.26..19.48行=8宽度=86)\n重新检查条件:(id=任意('4)D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D C C C C-E7 6-6 6 6-B5 C-B5 C-6 6 6-6 6 6-B5 6-6 6 6-B5 C C-B5 6 6-B5 6-B5 6-B5 6-6-B5 6-6-6-6-B5 6-6-6-6-6-6-B5 B5 B5 6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-B5 B5-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 56ca1}'::uuid[]))\n->身份验证时位图索引扫描\u permissionsvatnumber\u pkey(成本=0.00..9.26行=8宽度=0)\n索引条件:(id=ANY('4)D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D C C C C-E7 6-6 6 6-B5 C-B5 C-6 6 6-6 6 6-B5 6-6 6 6-B5 C C-B5 6 6-B5 6-B5 6-B5 6-6-B5 6-6-6-6-B5 6-6-6-6-6-6-B5 B5 B5 6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-B5 B5-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 56CA1}'::uuid[])”
>>>timeit(t_l,数字=10000)
0.9831858319999967
>>>时间单位(t_s,数字=10000)
0.7851520270000023
但我还想看看当列表和集合已经具有相同数量的唯一元素时会发生什么:

>>timeit(t\u l,数字=10000)
0.8463515899999976
>>>时间单位(t_s,数字=10000)
0.7903294700000174
事实证明,首先将列表转换为集合的速度更快,尽管差距要小得多。如果让我猜一猜,Django在将查询提交给DB之前,总是在内部运行某种列表到集合的转换