編集
質問を間違って読んだので、実際には2つの異なるクエリを調べて、それらの間の時間計算量を判断していることがわかりました。
最初のクエリは次のとおりです。
coll.update({}, {'$addToSet': {'a':1}}, multi=True)
そして2番目は:
coll.update({'a': {'$ne': 1}}, {'$push': {'a':1}}, multi=True)
ここで最初の問題が思い浮かびます。インデックスはありません。$addToSet
、更新修飾子であるため、必要なことを実行するために全表スキャンを実行しているようなインデックスを使用しているとは思いません。
1
実際には、まだ含まれていないすべてのドキュメントを探し、その配列の値をa
探しています。$push
1
a
したがって、最初のクエリは次のようになるため、ここで時間計算量に入る前でも、2は2番目のクエリを指します。
- インデックスを使用しません
- 全表スキャンになります
- 次に、(インデックスなしで)フルアレイスキャンを実行します
$addToSet
ですから、私はここで、2番目のクエリがBigO表記の前に探しているものであることをほぼ決心しました。
ここで各クエリの時間計算量を説明するために大きなO表記を使用することには問題があります。
- ドキュメントごとなのか、コレクション全体に対するものなのか、どのような視点が必要かわかりません。
- インデックス自体はわかりません。インデックスを使用すると、実際にはログアルゴリズムが作成されますが、インデックスを
a
使用しない場合は作成されません。
ただし、最初のクエリは次のようになります。ドキュメントごとのO(n)以降:
- $ addToSetは、各要素を反復処理する必要があります
- $ addToSetは、セットが存在しない場合、セットを挿入するためにO(1)操作を実行する必要があります。O(1)がキャンセルされているかどうかわからないことに注意する必要があります(軽い読みが私のバージョンを示唆しています)、ここでキャンセルしました。
コレクションごとに、インデックスがない場合は次のようになります。反復の複雑さはa
新しいドキュメントごとに指数関数的に増加するため、O(2n2)になります。
インデックスがない場合の2番目のクエリは、次のようになります。O(2n2)(ドキュメントごとにO(n))インデックスがない$ne
場合と同じ問題が発生するため、私は信じてい$addToSet
ます。ただし、インデックスの場合、これは実際にはO(log n log n)(O(log n)per document)になると思います。これは、bツリーに基づいて、最初にすべてのドキュメントが含まa
れ、次にすべてのドキュメントがセットに含まれないためです。1
したがって、時間計算量と最初のメモに基づいて、クエリ2の方が優れていると思います。
正直なところ、「ビッグO」表記で説明することに慣れていないので、これは実験的なものです。
それが役に立てば幸い、