クエリの最適化
インデックスは、クエリ操作で加工する必要があるデータ量を減らすことで、読み取り操作の効率を向上させます。これにより、MongoDB 内でクエリを実行する作業が簡素化されます。
読み取り操作をサポートするインデックスの作成
アプリケーションが特定のフィールドまたはフィールド セットのコレクションをクエリする場合、クエリされたフィールドのインデックスまたはフィールド セットの複合インデックスにより、クエリがコレクション全体をスキャンしてクエリ結果を検索して返すことを防ぐことができます。 インデックスの詳細については、「 MongoDB のインデックスに関する完全ドキュメント 」を参照してください
例
アプリケーションは、type
フィールドの inventory
コレクションをクエリします。type
フィールドの値はユーザー ドリブンです。
var typeValue = <someUserInput>; db.inventory.find( { type: typeValue } );
このクエリのパフォーマンスを向上させるには、 type
フィールドのinventory
コレクションに昇順または降順のインデックスを追加します。 [ 1 ] mongosh
では、 db.collection.createIndex()
メソッドを使用してインデックスを作成できます。
db.inventory.createIndex( { type: 1 } )
このインデックスにより、上記の type
のクエリがコレクション全体をスキャンして結果を返すのを防ぐことができます。
インデックスを使用してクエリのパフォーマンスを分析するには、説明計画結果の解釈 を参照してください。
読み取り操作の最適化に加えて、インデックスはソート操作をサポートし、より効率的なストレージ利用を可能にします。インデックス作成の詳細については、db.collection.createIndex()
および「インデックス」を参照してください。
[1] | 単一フィールド インデックスの場合、昇順か降順かの選択は重要ではありません。複合インデックスの場合、この選択は重要です。詳細については、「インデックス順序」を参照してください。 |
クエリの選択性
クエリの選択性とは、クエリ述語がコレクション内のドキュメントをどの程度適切に除外またはフィルタリングするかを指します。クエリの選択性によって、クエリがインデックスを効果的に使用できるかどうか、あるいはインデックスをまったく使用しないかが決まります。
選択性の高いクエリほど、一致するドキュメントの割合は少なくなります。たとえば、ユニークな _id
フィールドでの等価一致は、多くとも 1 件のドキュメントにしか一致しないため、選択性が非常に高くなります。
選択性の低いクエリは、一致するドキュメントの割合は多くなります。選択性の低いクエリは、インデックスを効果的に使用できない、あるいはまったく使用できません。
たとえば、不等式演算子 $nin
と $ne
は、インデックスの大部分と一致することが多いため、あまり選択的ではありません。その結果、多くの場合、インデックス付きの $nin
クエリまたは $ne
クエリのパフォーマンスは、コレクション内のすべてのドキュメントをスキャンする必要がある $nin
クエリまたは $ne
クエリのパフォーマンスと同程度になる可能性があります。
regular expressions
の選択性は式自体に依存します。詳細については、「正規表現とインデックスの使用」をご覧ください。
カバード クエリ
カバード クエリとは、インデックスを使用して処理が完了し、ドキュメントを調査する必要がないクエリです。次のすべてが当てはまる場合、インデックスはクエリをカバーします。
クエリ内のすべてのフィールド(アプリケーションによって指定されるフィールドと、シャーディング目的など内部で必要なフィールドの両方)は、インデックスの一部です。
結果で返されるすべてのフィールドは同じインデックス内にあります。
クエリ内のどのフィールドも
null
と等しくありません。例、次のクエリ述語ではカバード クエリは作成されません。{ "field": null }
{ "field": { $eq: null } }
例
inventory
コレクションでは、 フィールドとtype
item
フィールドには次のインデックスがあります。
db.inventory.createIndex( { type: 1, item: 1 } )
このインデックスは、type
フィールドとitem
フィールドをクエリし、item
フィールドのみを返す次の操作をカバーしています。
db.inventory.find( { type: "food", item:/^c/ }, { item: 1, _id: 0 } )
指定されたインデックスがクエリをカバーするには、インデックスに _id
フィールドが含まれていないため、プロジェクション ドキュメントは _id: 0
を明示的に指定して結果から _id
フィールドを除外する必要があります。
埋め込みドキュメント
インデックスは、埋め込みドキュメント内のフィールドに対するクエリをカバーできます。
例、次の形式のドキュメントを含むuserdata
コレクションを考えてみましょう。
db.userdata.insertOne( { _id: 1, user: { login: "tester" } } )
コレクションには、次のインデックスがあります。
db.userdata.createIndex( { "user.login": 1 } )
{ "user.login": 1 }
インデックスは次のクエリをカバーします。
db.userdata.find( { "user.login": "tester" }, { "user.login": 1, _id: 0 } )
注意
埋め込みドキュメントのフィールドにインデックスを付けるには、ドット表記を使用します。 「埋め込みフィールドでのインデックスの作成 」を参照してください。
マルチキーのカバーリング
マルチキー インデックスは、どのフィールドがインデックスをマルチキーにするかを追跡する場合、非配列フィールドに対するクエリをカバーできます。
マルチキー インデックスは、配列フィールドに対するクエリをサポートしていません。
マルチキーインデックスを使用したカバーされたクエリの例については、 マルチキー インデックスのページの「カバーされたクエリ」を参照してください。
パフォーマンス
インデックスにはクエリに必要なすべてのフィールドが含まれているため、MongoDB はクエリ条件を一致させることも、インデックスのみを使用して結果を返すこともできます。
インデックスのみをクエリする方が、インデックス外のドキュメントをクエリするよりもはるかに高速です。インデックス キーは通常、カタログするドキュメントよりも小さく、インデックスは通常 RAM で利用可能か、ディスク上に連続してに配置されます。
制限
インデックス タイプ
すべてのインデックスタイプがクエリをカバーできるわけではありません。カバードインデックスサポートの詳細については、対応するインデックスタイプのドキュメント ページを参照してください。
シャーディングされたコレクションの制限
mongos
で実行すると、インデックスにシャードキーが含まれている場合にのみ、シャーディングされたコレクションのクエリをカバーできます。
explain
カバード クエリであるかどうかを判断するには、 db.collection.explain()
} メソッドまたはexplain()
メソッドを使用します。 「カバード クエリ 」を参照してください。