编辑
好的,因为我一直都错误地阅读了您的问题,事实证明实际上您正在查看两个不同的查询并判断它们之间的时间复杂度。
第一个查询是:
coll.update({}, {'$addToSet': {'a':1}}, multi=True)
第二个是:
coll.update({'a': {'$ne': 1}}, {'$push': {'a':1}}, multi=True)
这里想到的第一个问题,没有索引。$addToSet
,作为更新修饰符,我不相信它使用索引,因为您正在执行全表扫描来完成您需要的操作。
实际上,您正在查找尚未包含的所有文档1
并a
查看该数组$push
的值。1
a
所以 2 甚至在我们进入时间复杂度之前就指向了第二个查询,因为第一个查询:
- 不使用索引
- 将是全表扫描
- 然后会做一个完整的数组扫描(没有索引)到
$addToSet
因此,我在这里几乎已经下定决心,第二个查询是您在使用任何大 O 表示法之前要查找的内容。
这里使用大 O 表示法来解释每个查询的时间复杂度是有问题的:
- 我不确定您想要什么视角,无论是每个文档还是整个集合。
- 我不确定索引本身。使用索引实际上会创建一个 Log 算法,
a
但不使用索引则不会。
然而,第一个查询看起来像:每个文档 O(n),因为:
- $addToSet 需要遍历每个元素
- 然后 $addToSet 需要执行 O(1) 操作来插入该集合(如果它不存在)。我应该注意我不确定 O(1) 是否被取消(轻微阅读表明我的版本),我在这里取消了它。
每个集合,如果没有索引,它将是:O(2n2),因为迭代的复杂性a
将随着每个新文档呈指数级增加。
没有索引的第二个查询看起来像: O(2n2) (O(n) per document) 我相信因为会出现与没有索引$ne
相同的问题。$addToSet
但是,对于索引,我相信这实际上是 O(log n log n) (每个文档 O(log n)),因为它会首先根据 b-tree找到所有包含在其中的文档a
,然后是所有不在其集合中的文档。1
因此,根据时间复杂度和开头的注释,我会说查询 2 更好。
老实说,我不习惯用“Big O”表示法解释,所以这是实验性的。
希望能帮助到你,