これが何を意味するのかを例で説明しようと思います。 Bツリーに基づくインデックスは、mongodb固有のものではありません。対照的に、それはかなり一般的な概念です。
したがって、インデックスを作成すると、データベースに何かを見つけるためのより簡単な方法が表示されます。ただし、このインデックスは、元のドキュメントの場所を指すポインタとともにどこかに保存されます。この情報は順序付けられており、非常に優れたプロパティを持つバイナリツリーと見なすことができます。検索はO(n)
から削減されます。 (線形スキャン)からO(log(n))
。スペースを半分にトリミングするたびに、これははるかに高速です(10 ^ 6から20ルックアップに時間を短縮できる可能性があります)。たとえば、フィールド{a : some int, b: 'some other things'}
を持つ大きなコレクションがあります。 そして、それをaでインデックス付けすると、a
でソートされた別のデータ構造になります。 。このように見えます(これは、別のコレクションであるという意味ではありません。これはデモンストレーション用です):
{a : 1, pointer: to the field with a = 1}, // if a is the smallest number in the starting collection
...
{a : 999, pointer: to the field with a = 990} // assuming that 999 is the biggest field
したがって、現在、フィールドa =18を検索しています。すべての要素を1つずつ調べる代わりに、真ん中に何かを取り、18より大きい場合は、下部を半分に分割して、そこで要素をチェックします。 。 a =18が見つかるまで続行します。次に、ポインターを調べて、元のフィールドを抽出することを確認します。
複合インデックスの状況も同様です(1つの要素で並べ替える代わりに、多くの要素で並べ替えます)。たとえば、コレクションがあります:
{ "item": 5, "location": 1, "stock": 3, 'a lot of other fields' } // was stored at position 5 on the disk
{ "item": 1, "location": 3, "stock": 1, 'a lot of other fields' } // position 1 on the disk
{ "item": 2, "location": 5, "stock": 7, 'a lot of other fields' } // position 3 on the disk
... huge amount of other data
{ "item": 1, "location": 1, "stock": 1, 'a lot of other fields' } // position 9 on the disk
{ "item": 1, "location": 1, "stock": 2, 'a lot of other fields' } // position 7 on the disk
インデックスが必要です{"item":1、 "location":1、 "stock":1}。ルックアップテーブルは次のようになります(もう一度-これは別のコレクションではなく、デモンストレーション用です):
{ "item": 1, "location": 1, "stock": 1, pointer = 9 }
{ "item": 1, "location": 1, "stock": 2, pointer = 7 }
{ "item": 1, "location": 3, "stock": 1, pointer = 1 }
{ "item": 2, "location": 5, "stock": 7, pointer = 3 }
.. huge amount of other data (but not necessarily here. If item would be one it would be somewhere next to items 1)
{ "item": 5, "location": 1, "stock": 3, pointer = 5 }
ここでは、すべてが基本的にアイテム、場所、ポインタの順に並べ替えられていることを確認してください。単一のインデックスの場合と同じように、すべてをスキャンする必要はありません。 item = 2, location = 5 and stock = 7
を検索するクエリがある場合 item = 2
のドキュメントがどこにあるかをすばやく特定できます 次に、同じ方法で、location 5
を使用してこれらのアイテムのどこにアイテムがあるかをすばやく特定します。 など。
そして今、興味深い部分 。また、インデックスを1つだけ作成しました(これは複合インデックスですが、それでも1つのインデックスです)。これを使用して、要素をすばやく見つけることができます
-
item
のみ 。本当に私たちがする必要があるのは最初のステップだけです。したがって、別のインデックス{location:1}はすでに複合インデックスでカバーされているため、作成する意味はありません。 - また、
item and by location
でのみすばやく見つけることができます (2つのステップだけが必要です)。
クールな1つのインデックスですが、3つの異なる方法で役立ちます。ただし、ちょっと待ってください。item and stock
で検索したい場合はどうでしょうか。 。ああ、このクエリも高速化できるようです。 log(n)で特定のアイテムを持つすべての要素を見つけることができ、...ここで停止する必要があります-魔法は終了しました。それらすべてを繰り返す必要があります。しかし、それでもかなり良いです。
しかし、それが他の質問に役立つかもしれません。 location
でクエリを見てみましょう すでに注文されたようです。しかし、それを見ると、これは混乱していることがわかります。最初に1つ、最後に1つ。それはあなたをまったく助けることができません。
これでいくつかのことが明らかになることを願っています:
- インデックスが優れている理由(O(n)から潜在的にO(log(n))に時間を短縮する
- 複合インデックスが一部のクエリに役立つのに、その特定のフィールドにインデックスを作成しておらず、他のクエリに役立つのはなぜですか。
- 複合インデックスの対象となるインデックス
- インデックスが害を及ぼす可能性がある理由(維持する必要のある追加のデータ構造を作成する)
そして、これは別の有効なことを伝えるはずです:インデックスは銀の弾丸ではありません 。すべてのクエリを高速化することはできないため、すべてのフィールドにインデックスを作成することですべてが超高速になると考えるのはばかげているように思えます。