複合インデックスは複数のフィールドを参照するため、クエリの応答時間を大幅に改善できます。
ほとんどの場合、ESR(Equality(等価)、Sort(並べ替え)、Range(範囲))のガイドラインを適用してインデックスキーを配置すると、より効率的な複合インデックスが作成されます。
等価フィールドが常に最初に配置されるようにします。最初に等価フィールドを配置すると、残りのインデックスフィールドがソート順で保持されます。インデックスの特定のニーズに基づいて、次にソートするフィールドと範囲フィールドのどちらを使用するかを選択します。
メモリ内ソートを避けることが重要な場合は、範囲フィールドの前にソート フィールドを配置します(ESR)
クエリの範囲述語が非常に選択的である場合は、ソートフィールドの前に配置してください(ERS)
クエリの最適化の詳細については、explain とクエリプランを参照してください。
Tip
インデックスをテストするときに、 MongoDBに特定のインデックスを使用させるには、 cursor.hint() (mongoshメソッド)を使用します。
Equality(等価)
Equality(等価)は、1つの値で完全に一致することを指します。次の完全一致クエリは、cars コレクションをスキャンして model フィールドが Cordoba と完全に一致するドキュメントを探します。
db.cars.find( { model: "Cordoba" } ) db.cars.find( { model: { $eq: "Cordoba" } } )
インデックス検索では、検査されたインデックスキーの数を減らすために完全一致が効率的に使用されます。等価フィールドは最初に指定する必要があります。
インデックスには複数の等価キーを含めることができます。これらは相互に対して任意の順序で表示できますが、すべての等価キーはいずれのソート フィールドまたは範囲フィールドに先行する必要があります。
等価一致の選択性が高いほど、インデックス クエリの効率が高くなります。
Sort
Sort(並べ替え)は、結果の順序を決定します。メモリ内でのソートを回避するには、インデックスの範囲の前にソート フィールドを配置します。
インデックスは、ソート キーに先行するすべてのプレフィックス キーに対して等価条件がクエリに含まれている場合にのみ、キーのサブセットに対するソート操作をサポートします。詳細については、ソートとインデックスのプレフィックス以外のサブセット を参照してください。
次の例では、cars コレクションをクエリします。出力はmodel でソートされます。
db.cars.find( { manufacturer: "GM" } ).sort( { model: 1 } )
クエリのパフォーマンスを向上させるには、manufacturer フィールドと model フィールドにインデックスを作成します。
db.cars.createIndex( { manufacturer: 1, model: 1 } )
manufacturerは等価一致であるため、最初のキーです。modelはクエリと同じ順序(1)でインデックス付けされます。
Range(範囲)
「範囲」フィルターは、フィールドをスキャンします。 スキャンでは完全一致は必要ないため、範囲フィルターはインデックス キーに緩やかに結合されます。 クエリの効率を向上させるには、範囲の境界を制限し、等価一致を使用してスキャンするドキュメント数を減らします。
範囲フィルターは次のようになります。
db.cars.find( { price: { $gte: 15000} } ) db.cars.find( { age: { $lt: 10 } } ) db.cars.find( { priorAccidents: { $ne: null } } )
クエリ内の範囲述語が非常に選択的である場合は、ソートされたドキュメントの数を減らし、メモリ内でソートできるようにするために、ソートフィールドの前にそれを配置してください。
メモリ内ソートを回避するには、ソート述語の後に範囲フィルターを配置します。メモリ内ソートの詳細については、cursor.allowDiskUse() を参照してください。
その他の考慮事項
$regexは範囲演算子です。$inを単独で使用した場合、それは一連の等価一致を実行する等価演算子になります。$inを.sort()と併用する場合$inの配列要素が200より小さい場合、要素は展開され、インデックスに指定されたソート順でマージされます。 これにより、小規模な配列のパフォーマンスが向上します。$inは、ESR を持つ等価述語に似ています。$inに200以上の要素がある場合、要素は範囲演算子のように順序付けられます。 このシナリオでは、小さな配列のパフォーマンス向上は実現されません。 インデックス内の後続のフィールドではソートを提供できず、$inは ESR 付きの範囲述語に似ています。通常、小さな配列で
$insを使用する場合は、インデックス指定に$insを早めに含めます。通常、大きな配列を使用する場合は、範囲述語を含める場所に$insを含めます。
注意
200の制限は変更される可能性があり、すべての MongoDB バージョンで同じであることが保証されません。
例
次のクエリは、cars コレクションで、コストが 15,000 ドルを超える Ford 製の車両を検索します。結果はモデル別にソートされます。
db.cars.find( { manufacturer: 'Ford', cost: { $gt: 15000 } } ).sort( { model: 1 } )
クエリには、ESR ガイドラインのすべての要素が含まれています。
manufacturer: 'Ford'は等価ベースの一致ですcost: { $gt: 15000 }は、範囲ベースの一致ですmodelはソートに使用されます
ESR ガイドラインに従うと、例クエリに最適なインデックスは次のようになります。
{ manufacturer: 1, model: 1, cost: 1 }