web-dev-qa-db-ja.com

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

docs を引用するには:

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

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

103
johndodo

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

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

BTreeでのレコードの検索には、O(Log(n))時間)が必要です。レコードの範囲を順番に検索するのは、OLog(n)+ kのみです(kは返すレコードの数)。

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

98
Jared Kells

単純な答え探しているのは、方向が重要なのは、2つ以上のフィールドでソートするときだけであるということです。

{a : 1, b : -1}でソートしている場合:

インデックス{a : 1, b : 1}は、より遅いインデックス{a : 1, b : -1}

42
Zaid Masud

なぜインデックス

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

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

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

どのようにインデックス

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

ソートする理由

クエリには並べ替えが必要な場合があります。ただし、並べ替えはコストのかかる操作になる可能性があるため、並べ替えているフィールドを、クエリを実行しているフィールドと同様に扱うことが重要です。そのため、インデックスがあれば高速になります。ただし、重要な違いが1つあります。ソートするフィールドは、インデックスの最後のフィールドでなければなりません。この規則の唯一の例外は、フィールドがクエリの一部でもある場合、last-be-be-last-ruleは適用されません。

ソート方法

インデックスのすべてのキーまたはサブセットでソートを指定できます。ただし、ソートキーは、インデックスに表示されるのと同じ順序でリストする必要があります。たとえば、インデックスキーパターン{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 }
10
Somnath Muluk