ソート順が指定されていない場合、MongoDBはどのようにレコードをソートしますか?


103

並べ替え順序を指定せずにMongo find()クエリを実行すると、データベースは結果を並べ替えるために内部的に何を使用しますか?

mongoウェブサイトのドキュメントによると:

パラメーターを指定せずにfind()を実行すると、データベースはオブジェクトを順自然順で返します。

標準の表の場合、自然順序は特に有用ではありません。これは、順序が挿入順序に近いことが多いが、保証されるわけではないためです。ただし、制限付きコレクションの場合、自然順序が挿入順序であることが保証されています。これは非常に便利です。

ただし、標準のコレクション(上限のないコレクション)の場合、結果の並べ替えにはどのフィールドが使用されますか?それは_idフィールドまたは他の何か?

編集:

基本的に、私が得ようとしているのは、次の検索クエリを実行した場合だと思います。

db.collection.find({"x":y}).skip(10000).limit(1000);

2つの異なる時点:t1t2で、異なる結果セットが得られますか?

  1. t1とt2の間に追加の書き込みがなかった場合はどうなりますか?
  2. t1とt2の間に新しい書き込みがあったときは?
  3. t1とt2の間に追加された新しいインデックスはありますか?

一時データベースでいくつかのテストを実行しましたが、取得した結果は3つのケースすべてで同じです(はい)。

回答:


121

何も指定されていない場合のデフォルトのソート順は何ですか?

デフォルトの内部ソート順(または自然順)は、未定義の実装詳細です。順序を維持することはストレージエンジンの追加のオーバーヘッドであり、MongoDBのAPIはsort()使用制限が関連付けられている固定サイズの上限付きコレクションの明示的または特殊なケース以外では予測可能性を要求しません。典型的なワークロードの場合、ストレージエンジンが利用可能な事前割り当て領域を再利用して、データをディスクとメモリに最も効率的に格納する方法を決定することが望ましいです。

クエリ条件がない場合、結果はストレージエンジンによって自然な順序でつまり、見つかった順序で)返されます。結果の順序は挿入の順序と一致する場合がありますが、この動作は保証されておらず、(上限のあるコレクションを除いて)信頼することはできません。

ストレージの(自然な)順序に影響を与える可能性があるいくつかの例:

  • WiredTigerは、ディスク上のドキュメントとメモリ内キャッシュのドキュメントの異なる表現を使用するため、内部のデータ構造に基づいて自然な順序が変わる場合があります。
  • オリジナルのMMAPv1ストレージエンジン(MongoDB 4.2で削除)は、パディングルールに基づいてドキュメントにレコードスペースを割り当てます。ドキュメントが現在割り当てられているレコードスペースを超えると、ドキュメントの場所(および自然な順序)が影響を受けます。削除または移動されたドキュメントのために、再利用可能としてマークされたストレージに新しいドキュメントを挿入することもできます。
  • レプリケーションは、べき等のoplog形式を使用して、レプリカセットメンバー全体に一貫して書き込み操作を適用します。各レプリカセットメンバーは、自然な順序で変化する可能性があるローカルデータファイルを保持しますが、oplog更新が適用されると同じデータ結果になります。

インデックスが使用されている場合はどうなりますか?

インデックスを使用すると、ドキュメントは見つかった順序で返されます(挿入順序またはI / O順序と必ず一致します)。複数のインデックスが使用されている場合、順序は重複排除プロセス中にドキュメントを最初に識別したインデックスに内部的に依存します。

予測可能な並べ替え順序が必要な場合は、sort()クエリに明示的なものを含め、並べ替えキーに一意の値を含める必要があります。

キャップされたコレクションはどのように挿入順序を維持しますか?

上限付きコレクションでの自然順序について言及されている実装の例外は、特別な使用制限によって適用されます。ドキュメントは挿入順に保存されますが、既存のドキュメントサイズを大きくしたり、ドキュメントを明示的に削除したりすることはできません。順序付けは、最も古いドキュメントが最初に「期限切れ」になるように制限されたコレクションデザインの一部です。


4
つまり、同じ検索コマンドを実行すると、db.collection.find({"x":y})。skip(20000).limit(1000)が2つの異なる時点で実行されると、異なる結果が得られます。セット?2つのコマンドの間に書き込みがなかった場合はどうなりますか?
saurabhj 2012

6
@saurabhj:自然順序に影響を与えるいくつかの例を追加しました。ドキュメントが移動または削除された場合、異なる結果セットが表示される可能性があります。ドキュメントの挿入/更新/削除がない場合でも、同じ結果が得られるはずです。インデックスを追加しても、ディスク上のドキュメントの場所には影響しません。
ステニー

7
レプリケーションを使用している場合、自然な順序はレプリカセットメンバー間で異なる可能性があるという警告も追加する必要があります。
ステニー

ここにコメントされている2つのポイントのいずれかを強制する方法を誰かが知っていますか?ドキュメントを変更しようとしましたが、それらはまだ挿入順序で返されます...自然な順序が挿入順序と異なることがあるかどうか知りたいです。
Ferran Maylinch

{createdAt: -1}オプティミスティックUIパターンを実装するには、デフォルトの順序(たとえば)を適用する必要があります(作成/更新/削除後のサーバーの応答を待たずにキャッシュ内のデータのリストを更新します)。そうしないと、クライアント側の楽観的順序とサーバーの応答順序を一致させることができません。
Eric Burel

8

格納された順序(ファイル内の順序)で返されますが、挿入された順序であるとは限りません。それらは_idフィールドでソートされません。挿入順にソートされているように見えることもありますが、別のリクエストで変更される場合があります。信頼できません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.