Learn the "why" behind slow queries and how to fix them in our 2-Part Webinar.
Register now >
Docs Menu
Docs Home
/ /

クエリの最適化

クエリの最適化により、クエリが処理する必要があるデータ量が削減されます。インデックス、プロジェクション、クエリ制限を使用して、パフォーマンスを向上させ、リソース消費を削減します。コレクションが大きくなるにつれてクエリのパフォーマンスを定期的に検討して、増やすを判断します。

インデックスはフィールド値を別のデータ構造に保存します。読み取り操作では、 MongoDB はコレクション全体をスキャン するのではなく、インデックスを検索します。書込み操作では、 MongoDB はコレクションとインデックス の両方を更新します。

最も一般的なクエリのインデックスを作成します。クエリが複数のフィールドを検索する場合は、複合インデックスを作成します。

例、inventoryコレクションの typeフィールドに対する次のクエリを考えてみましょう。

let typeValue = <someUserInput>;
db.inventory.find( { type: typeValue } );

このクエリのパフォーマンスを向上させるには、 typeフィールドにインデックスを追加します。

db.inventory.createIndex( { type: 1 } )

[1] mongosh では、db.collection.createIndex() を使用します。

クエリのパフォーマンスを分析するには、説明計画結果の解釈を参照してください。

[1] 単一フィールド インデックスの場合、インデックスの順序は重要ではありません。複合インデックスの場合、フィールドの順序はインデックスがサポートするクエリに影響します。詳細については、「複合インデックスのソート順序」を参照してください。

クエリの選択性は、クエリ述語がドキュメントをどの程度フィルターするかを測定し、クエリがインデックスを効果的に使用できるかどうかを判断します。

  • 選択性の高いクエリは、一致するドキュメントが少なく、インデックスをより効果的に使用します。インスタンス、_id の等価一致は、多くとも 1 件のドキュメントにしか一致しないため、選択性が非常に高くなります。

  • 選択性の低いクエリは、一致するドキュメントの数が多くなり、インデックスの使用効率が低くなります。

たとえば、不等式演算子 $nin$ne は、インデックスの大部分と一致することが多いため、あまり選択的ではありません。その結果、多くの場合、インデックス付きの $nin クエリまたは $ne クエリのパフォーマンスは、コレクション内のすべてのドキュメントをスキャンする必要がある $nin クエリまたは $ne クエリのパフォーマンスと同程度になる可能性があります。

regular expression の選択性は式自体に依存します。詳細については、正規式とインデックスの使用をご覧ください。

ドキュメントの一部のフィールドセットが必要な場合は、必要なフィールドのみを返すことでパフォーマンスを向上できます。プロジェクションにより、ネットワーク トラフィックと処理時間が削減されます。

例、timestamptitleauthorabstract フィールドのみを返すには、次のクエリを考慮します:

db.posts.find(
{},
{ timestamp : 1, title : 1, author : 1, abstract : 1}
).sort( { timestamp : -1 } )

$project集計ステージを使用する場合、それは通常パイプラインの 最後のステージ であり、クライアントに返すフィールドを指定するために使用されます。

$project ステージをパイプラインの開始または中間で使用して、後続のパイプラインステージに渡されるフィールドの数を減らしてもパフォーマンスが改善する可能性はほとんどありません。データベースではこの最適化が自動的に実行されているためです。

詳細については、「クエリから返されるプロジェクト フィールド」を参照してください。

カバード クエリを実行するには、プロジェクション フィールドにインデックス。ESR(Equality, Sort, 範囲)ルールは、インデックス内のフィールドの順序に適用されます。

例、inventoryコレクションの次のインデックスについて考えてみます。

db.inventory.createIndex( { type: 1, _id: 1, price: 1, item: 1, expiryDate: 1} )

上記のクエリは技術的には正しいですが、クエリ パフォーマンスを最適化するように構成されていません。

次のクエリは、より効率的な複合インデックスの ESR ルールを適用します。

db.inventory.aggregate([
{ $match: {type: "food", expiryDate: { $gt: ISODate("2025-07-10T00:00:00Z") }}},
{ $sort: { item: 1 }},
{ $project: { _id: 1, price: 1} }
])

インデックスとクエリは ESR ルールに従います。

  • type は等価一致(E)に使用されるため、インデックスの最初のフィールドになります。

  • item はソート(S)に使用されるため、インデックスの type 後にあります。

  • expiryDate は範囲クエリ(R )に使用されるため、インデックスの最後のフィールドになります。

MongoDBカーソルは結果をバッチで返します。必要な結果の数がわかっている場合は、その値を limit() メソッドに渡して、ネットワークリソースの使用量を減らします。

どのドキュメントが返されるかを把握するために、ソート後に結果を制限します。例、次のクエリは、postsコレクションからの 10 の最新の結果のみを返します。

db.posts.find().sort( { timestamp : -1 } ).limit(10)

詳細については、limit() を参照してください。

クエリオプティマイザは、特定の操作に最適なインデックスを選択します。ただし、hint() メソッドを使用して特定のインデックスを強制できます。これは、パフォーマンス テストやフィールドが複数のインデックスに表示され、 MongoDB が使用するインデックスを保証する必要がある場合に役立ちます。

ドキュメント内の値を増減するには、$inc 演算子を使用します。演算子は、ドキュメントを選択し、クライアント側で簡単な変更を加えてからドキュメントをサーバーに書き込む代わりに、サーバー側でフィールド値を増加します。さらに、 演算子は、複数のアプリケーションインスタンスが同時に同じフィールドを更新するときに競合状態を防ぎます。

カバード クエリとは、ドキュメントを調査することなく、インデックスによって完全に満たすことができるクエリです。次のすべてが当てはまる場合、インデックスはクエリを カバー します。

  • クエリ内のすべてのフィールド(アプリケーションによって指定されたフィールドと、シャーディングなどの内部で必要なフィールドを含む)は、インデックスの一部です。

  • 結果に返されるすべてのフィールドは同じインデックスにある

  • クエリ内のどのフィールドも null に等しくありません。たとえば、次のクエリ述語ではカバード クエリは作成されません。

    • { "field": null }

    • { "field": { $eq: null } }

inventory コレクションの type フィールドと item フィールドには次のインデックスがあります。

db.inventory.createIndex( { type: 1, item: 1 } )

このインデックスは次のクエリをカバーします。このクエリは typeitem でフィルタリングし、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 }
)

注意

埋め込みドキュメントのフィールドにインデックスを付けるには、ドット表記を使用します。「埋め込みフィールドでのインデックスを作成する」を参照してください。

マルチキー インデックスは、どのフィールドがマルチキーを作成するかをインデックスで追跡する場合、非配列フィールドに対するクエリをカバーできます。

マルチキー インデックスは、配列フィールドに対するクエリをサポートしていません。

例については、マルチキー インデックス ページの「対象クエリ」を参照してください。

対象のクエリはクエリ条件を一致し、インデックスのみを使用して結果を返します。これは、インデックスキーが通常ドキュメントよりも小さく、インデックスは通常RAMまたはディスク上に連続して保存されるため、ドキュメントを取得するよりも高速です。

すべてのインデックスタイプがカバード クエリをサポートしているわけではありません。具体的なインデックスタイプについては、ドキュメントを参照してください。

mongos で実行すると、インデックスにシャードキーが含まれている場合にのみ、シャーディングされたコレクションのクエリをカバーできます。

クエリがカバーされているかどうかを確認するには、db.collection.explain() または explain() を使用します。カバード クエリ を参照してください。

戻る

因果整合性と、読み取り保証(read concern)および書込み保証(write concern)

ルール バッジを取得する

「クエリの最適化」を無料でマスターしましょう!

詳細

項目一覧