複合インデックス
MongoDBは複合インデックスをサポートしており、1 つのインデックス構造がコレクションのドキュメント内の複数のフィールド[1]への参照を保持します。 以下の図は、2 つのフィールドの複合インデックスの例を示しています。
[1] | MongoDBは、任意の複合インデックスに対して32フィールドの制限を課します。 |
複合インデックスは、複数のフィールドに一致するクエリをサポートできます。
互換性
MongoDB Atlas でホストされている配置では複合インデックスを使用できます。
MongoDB Atlas でホストされている配置のインデックスの管理の詳細については、「インデックスの作成、表示、削除、および非表示 」を参照してください。
複合インデックスの作成
複合インデックスを作成するには、次のプロトタイプのような操作を使用します。
db.collection.createIndex( { <field1>: <type>, <field2>: <type2>, ... } )
インデックス フィールドの順序は、特定のクエリに対する特定のインデックスの有効性に大きな影響を与えます。 ほとんどの複合インデックスでは、 ESR(Equality、Sort、Range)ルールに従うと、効率的なインデックスを作成するのに役立ちます。
重要
MongoDB 4.4 以降:
複合インデックスには、単一のハッシュされたインデックス フィールド を含めることができます。
MongoDB 4.2 またはそれ以前の場合は、
複合インデックスには、 ハッシュされたインデックス フィールド を含めることはでき ません 。
次のドキュメントのようなドキュメントを含む products
という名前のコレクションについて考えてみましょう。
{ "_id": ObjectId(...), "item": "Banana", "category": ["food", "produce", "grocery"], "location": "4th Street Store", "stock": 4, "type": "cases" }
次の操作では、 フィールドと フィールドに昇順のインデックスが作成されます。item
stock
db.products.createIndex( { "item": 1, "stock": 1 } )
複合インデックスにリストされるフィールドの順序は重要です。 インデックスには、 item
フィールドの値で最初にソートされ、 item
フィールドの各値内では 株式フィールドの値でソートされたドキュメントへの参照が含まれます。 詳細については、「ソート順序」を参照してください。
複合インデックスは、すべてのインデックス フィールドに一致するクエリをサポートするだけでなく、インデックス フィールドのプレフィックスに一致するクエリをサポートできます。 つまり、インデックスはitem
フィールドと、item
フィールドとstock
フィールドの両方に対するクエリをサポートしています。
db.products.find( { item: "Banana" } ) db.products.find( { item: "Banana", stock: { $gt: 5 } } )
詳細については、「プレフィックス 」を参照してください。
並び替え順
インデックスには、フィールドへの参照が昇順( 1
)または降順( -1
)のソート順序で保存されます。 単一フィールド インデックスの場合、MongoDB はどちらの方向にもインデックスをトラバースできるため、キーのソート順序は重要ではありません。 ただし、複合インデックスの場合、ソート順序がインデックスでソート操作をサポートできるかどうかの判断で重要になる場合があります。
フィールドusername
とdate
を持つドキュメントを含むコレクションevents
について考えます。 アプリケーションは、最初にusername
値の昇順でソートされ、次に (直近のdate
値の降順)ソートされた結果を返すクエリを発行できます。たとえば、次のようなクエリを発行できます。
db.events.find().sort( { username: 1, date: -1 } )
または クエリのように、最初にusername
値の降順でソートされ、次にdate
値の昇順でソートされた結果を返すクエリは、次のようになります。
db.events.find().sort( { username: -1, date: 1 } )
次のインデックスは、これらの両方のソート操作をサポートできます。
db.events.createIndex( { "username" : 1, "date" : -1 } )
ただし、上記のインデックスでは、次のようなusername
値の昇順、その後にdate
値の昇順によるソートをサポートしていません。
db.events.find().sort( { username: 1, date: 1 } )
ソート順序と複合インデックスの詳細については、「クエリ結果をソートするためにインデックスを使用する 」を参照してください。
プレフィックス
インデックスのプレフィックスは、インデックス フィールドの開始サブセットです。 たとえば、次の複合インデックスについて考えてみます。
{ "item": 1, "location": 1, "stock": 1 }
インデックスには以下のようなプレフィックスがあります。
{ item: 1 }
{ item: 1, location: 1 }
複合インデックスの場合、MongoDB はインデックスを使用してインデックス プレフィックスに対するクエリをサポートできます。 そのため、MongoDB は次のフィールドに対するクエリにインデックスを使用できます。
item
フィールドitem
フィールドとlocation
フィールドitem
フィールドとlocation
フィールドとstock
フィールド
MongoDB では、 item
フィールドがプレフィックスに対応しているため、インデックスを使用してitem
フィールドとstock
フィールドに対するクエリをサポートすることもできます。 ただし、この場合、インデックスがitem
とstock
のみにある場合のように、インデックスはクエリをサポートする際に効率的ではありません。 インデックス フィールドは順番に解析されます。クエリで特定のインデックス プレフィックスが省略された場合、そのプレフィックスに続くインデックス フィールドは使用できません。
item
とstock
のクエリではlocation
インデックス プレフィックスが省略されるため、 location
stock
インデックス フィールドは使用できません。 このクエリをサポートできるのはインデックス内のitem
フィールドのみです。 詳細については、 「 クエリをサポートするインデックスの作成」を参照してください。
MongoDB では、 item
フィールドがない場合、リストされたフィールドはいずれもプレフィックス インデックスに対応しないため、インデックスを使用して次のフィールドを含むクエリをサポートすることはできません。
location
フィールドstock
フィールド、またはlocation
フィールドとstock
フィールド。
複合インデックスとそのプレフィックスの両方を持つコレクションがある場合(例: { a: 1, b: 1 }
と{ a: 1 }
)の場合、どちらのインデックスにも スパース 性の制約または 一意の 制約がない場合は、プレフィックスのインデックスを除くことができます(例: { a: 1 }
)。 MongoDB では、プレフィックス インデックスを使用していたであろうすべての状況で複合インデックスが使用されます。
インデックスの交差
バージョン 2.6 以降では、MongoDB はインデックスの交差を使用してクエリを実行できます。 クエリをサポートする複合インデックスを作成するか、インデックスの交差に依存するかは、システムの仕様によって異なります。 詳細については、「インデックスの交差と複合インデックス」を参照してください。
スパース複合インデックス
複合インデックスには、さまざまなタイプのスパースインデックスを含めることができます。インデックスのタイプの組み合わせによって、複合インデックスがドキュメントと一致する方法が決まります。
下表には、さまざまなタイプのスパースインデックスを含む複合インデックスの動作がまとめられています。
複合インデックスの構成要素 | 複合インデックスの動作 |
---|---|
Ascending indexes Descending indexes | 1 つ以上のキーの値を含むドキュメントのみ、インデックスが作成されます。 |
geospatial フィールドのいずれかに値が含まれている場合にのみ、ドキュメントのインデックスが作成されます。昇順または降順インデックス形式のドキュメントのインデックスは作成されません。 | |
text フィールドのいずれかに一致するドキュメントのみ、インデックスが作成されます。昇順または降順インデックス形式のドキュメントのインデックスは作成されません。 |
その他の考慮事項
インデックスの構築中に、アプリケーションはインデックスが作成されるコレクションへのパフォーマンスの低下や読み取り/書き込みアクセスの制限が発生することがあります。
インデックス構築プロセスの詳細については、「入力済みコレクションでのインデックス構築 」、特に「 レプリケートされた環境でのインデックス構築 」セクションを参照してください。
一部のドライバーは、インデックス順序を指定するために、NumberLong(1)
ではなく1
を使用します。結果として得られるインデックスは同じです。