MongoDBでインデックスの方向が重要なのはなぜですか?


114

ドキュメントを引用するには:

インデックスを作成するとき、キーに関連付けられた番号はインデックスの方向を指定するため、常に1(昇順)または-1(降順)である必要があります。方向は、単一のキーインデックスやランダムアクセス検索では重要ではありませんが、複合インデックスで並べ替えや範囲クエリを実行する場合は重要です。

ただし、複合インデックスでインデックスの方向が重要である理由はわかりません。誰かがさらに説明(または例)を提供できますか?

回答:


111

MongoDBは、何らかの方法で複合キーを連結し、それをBTreeのキーとして使用します。

単一のアイテムを見つけるとき -ツリー内のノードの順序は関係ありません。

ノードの範囲を返す場合 -互いに近い要素は、ツリーの同じブランチの下にあります。ノードが範囲内に近ければ近いほど、ノードをすばやく取得できます。

単一のフィールドインデックスの場合 -順序は関係ありません。昇順で接近している場合は、降順でも接近しています。

複合キーがある場合 -順序が重要になります。

たとえば、キーがA昇順B昇順の場合、インデックスは次のようになります。

行AB
1 1 1
2 2 6
3 2 7 
4 3 4
5 3 5
6 3 6
7 5 1

A昇順B降順のクエリでは、行を返すためにインデックスを順不同でジャンプする必要があり、速度が低下します。たとえば、行を返します1, 3, 2, 6, 5, 4, 7

インデックスと同じ順序の範囲クエリは、行を正しい順序で順番に返すだけです。

BTreeでレコードを検索するには、O(Log(n))時間かかります。レコードの範囲を順番に検索するのはOLog(n)+ kのみです。ここで、kは返されるレコードの数です。

レコードが順不同である場合、コストはOLog(n)* kと同じくらい高くなる可能性があります


1
結果の行はおそらく1, 3, 2, 6, 5, 4, 7
johndodo 2012

それが遅くなる理由はまだわかりません。アルゴリズムのみが異なる必要があります(Aの値のグループごとに、グループの最後にジャンプして逆の順序で処理する必要があります)。ただし、MongoDBインデックスはメモリ内にあるため、速度に顕著な影響はありません。また、RDBMSはインデックスの方向性について何も知らず、状況は非常によく似ています。
johndodo 2012

8
パフォーマンスに影響があるのは、単純化された例のようにメモリ内の単なる連続したリストではないためです。それは実際には加重ツリーです。順不同でジャンプすると、再びツリーをたどることになります。RDMSは間違いなくインデックスへの順序を持​​っています。
Jared Kells 2012

1
BTreeからノードを順番に取得するのは、実行するまで各リーフに沿って移動し、次にレベルを上げて次のブランチに進むのと同じくらい簡単です。それはO(n)です。順不同であると、CPUに負荷がかかります。
Jared Kells 2012

さらに説明していただきありがとうございます。MySQLインデックスのドキュメントを確認しました-インデックスの方向を指定することは実際には可能ですが、設定は無視されます。
johndodo 2012

45

簡単な答えあなたが探していることは、方向があることであるあなたが2つ以上のフィールドでソートされている場合にのみ重要

並べ替える場合{a : 1, b : -1}

インデックス{a : 1, b : 1}はインデックスよりも遅くなります{a : 1, b : -1}


1
@MarkPieszakは、ソート全体をメモリ内で実行する必要があるため、インデックスが役に立たなくなるためです
Sammaye

@Sammaye私はそれが正しい考えだと思いますが、それがすべての種類であるかどうかはわかりません。実際にどのように機能するかを知るために実装を調べる必要がありますが、結果を単独でソートし戻すことができ、その後、追加のbソートをメモリで実行する必要があると思います。
Zaid Masud

1
うーん、前回奇妙なことに、コードをチェックしたところ、並べ替えの方法が原因で部分的な並べ替えが削除されましたが、おそらく変更されました
Sammaye

でソートしている場合{a: -1, b: -1}{a: -1, b: -1}インデックスが{a: 1, b: 1}あれば十分でしょうか?
フセイン

あなたの例では@Hussainは{a: 1, b: 1}、インデックスを完全に逆にすることで十分なので、インデックスで十分です。たとえば、インデックスオン{a: 1}を使用して並べ替えを行うことができます。{a: -1}
Zaid Masud

12

なぜインデックスなのか

2つの重要なポイントを理解します。

  1. インデックスはインデックスがないよりも優れていますが、正しいインデックスはどちらよりも優れています。
  2. MongoDBはクエリごとに1つのインデックスのみを使用し、適切なフィールドの順序で使用したい複合インデックスを作成します。

インデックスは無料ではありません。これらはメモリを消費し、挿入、更新、削除を行うときにパフォーマンスを低下させます。通常、パフォーマンスへの影響は無視できます(特に、読み取りパフォーマンスの向上と比較して)が、それは、インデックスの作成がうまくいかないことを意味するものではありません。

インデックスの方法

一緒にインデックスを作成する必要があるフィールドのグループを識別することは、実行しているクエリを理解することです。インデックスの作成に使用されるフィールドの順序は重要です。良いニュースは、順序を間違えた場合、インデックスはまったく使用されないため、説明を見つけるのが簡単になるということです。

なぜソートするのか

クエリには並べ替えが必要な場合があります。ただし、並べ替えは負荷の高い操作になる可能性があるため、並べ替えの対象となるフィールドを、クエリを実行するフィールドと同じように扱うことが重要です。したがって、インデックスがある場合は高速になります。ただし、重要な違いが1つあります。並べ替えるフィールドは、インデックスの最後のフィールドでなければなりません。このルールの唯一の例外は、フィールドもクエリの一部である場合、最後の必須ルールは適用されません。

並べ替え方法

インデックスのすべてのキーまたはサブセットでソートを指定できます。ただし、ソートキーは、インデックスに表示されるのと同じ順序でリストする必要があります。たとえば、インデックスキーパターン{a:1、b:1}は、{a:1、b:1}の並べ替えをサポートできますが、{b:1、a:1}の並べ替えはサポートしません。

並べ替えは、すべてのキーに対して同じ並べ替え方向(昇順/降順)をインデックスキーパターンとして指定するか、すべてのキーに対して逆の並べ替え方向をインデックスキーパターンとして指定する必要があります。たとえば、インデックスキーパターン{a:1、b:1}は、{a:1、b:1}および{a:-1、b:-1}の並べ替えをサポートできますが、{a:-1の並べ替えはサポートしません。 、b:1}。

次のインデックスがあるとします。

{ a: 1 }
{ a: 1, b: 1 }
{ a: 1, b: 1, c: 1 }

Example                                                    Index Used
db.data.find().sort( { a: 1 } )                            { a: 1 }
db.data.find().sort( { a: -1 } )                           { a: 1 }
db.data.find().sort( { a: 1, b: 1 } )                      { a: 1, b: 1 }
db.data.find().sort( { a: -1, b: -1 } )                    { a: 1, b: 1 }
db.data.find().sort( { a: 1, b: 1, c: 1 } )                { a: 1, b: 1, c: 1 }
db.data.find( { a: { $gt: 4 } } ).sort( { a: 1, b: 1 } )   { a: 1, b: 1 }

私はそれが例であることを理解して{ a: 1, b: 1, c: 1 }いますが、インデックスがある場合、本当にインデックスが必要ですか{ a: 1}{ a: 1, b: 1}またはインデックス{ a: 1, b: 1, c: 1 }がすべてのケースをカバーしますか?クエリが常に同じ並べ替えを使用する場合:1クエリの並べ替えは-1ではありません
Lukas Liesis

1
プロパティ 'a'のみで機能するクエリが多い場合、データベースエンジンのプロパティ 'a'のインデックスで検索する方が、3つのプロパティ 'a'、 'b'、 'c'のインデックスで検索するよりも高速です。インデックスサイズが増加し、カウントも増加するためです。例 本に20章がある場合。したがって、第3章に移動してから特定のページに移動する方が高速です。@LukasLiesis
Somnath
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.