AI エージェント向け: ドキュメントインデックスは https://www.mongodb.com/ja-jp/docs/llms.txt で利用できます。すべてのページの markdown バージョンは、いずれかの URL パスに .md を追加することで利用できます。
Docs Menu

クエリプラン

MongoDB クエリ プランナーは、どのクエリに対しても、使用可能なインデックスを考慮して最も効率的なクエリプランを選択し、キャッシュします。プランナーは、クラシックなマルチプランナーまたはコストに基づいたランカー (CBR) のいずれかを使用してプランを選択できます。

従来のマルチプランナーでは、勝利プランは、試用期間中に最も少ない作業を実行しながら最も多くの結果を生成するクエリプランです。

MongoDB 8.3 以降、コストベースのランカー バックアップを使用したマルチプランニングが、対象となるクエリのデフォルトのプラン選択メカニズムになりました。短期の試用期間、マルチプランナーは、期間内に結果を返すことができるプランを検索します。

試行が失敗した場合、MongoDB は一連のルールを適用して、マルチプランナーを続行するか、CBR がプランを評価して最適なソリューションを決定するかを決定します。CBR は、コスト関数と濃度推定に基づいて、プラン内の各ノードを評価します。MongoDB は、最低の総合コストを持つプランを勝利プランとして選択します。現在、MongoDB はごく一部のクエリにのみ CBR を呼び出します。

いずれのランキングメカニズムも、選択したプランをクエリプランキャッシュに保存し、同じプランキャッシュクエリシェイプを持つ後続のクエリに再利用します。このページの残りの部分では、プランキャッシュの動作と、両方のメカニズムに適用される関連する概念について説明します。

以下の図はクエリプランナーのロジックを示しています。

MongoDB のクエリプランナー ロジックの図。
クリックして拡大します

注意

explainを使用すると、既存のすべてのプラン キャッシュ エントリが無視され、MongoDB クエリ プランナーが新しいプラン キャッシュ エントリを作成できなくなります。

各プラン キャッシュ クエリシェイプは、キャッシュ内の次の 3 つの状態のうちのいずれか 1 つに関連付けられています。

状態
説明

このシェイプのエントリはキャッシュに存在しません。

クエリで、プランキャッシュクエリシェイプのキャッシュエントリ状態が「欠落」の場合:

  1. 候補プランが評価され、勝者となるプランが選択されます。

  2. キャッシュは、プランに必要な作業量を定量化する値を持つ、非アクティブ状態のプランキャッシュクエリシェイプのエントリを作成します。

キャッシュ内のエントリは、このシェイプのプレースホルダー エントリです。つまり、プランナーはシェイプを参照して、プランに必要な作業量を定量化する値を計算し、シェイププレースホルダーエントリを保存しましたが、プランキャッシュクエリシェイプはクエリプランの生成には使用されません

クエリの場合、シェイプのキャッシュエントリ状態が 非アクティブ な場合、次のようになります。

  1. 候補プランが評価され、勝者となるプランが選択されます。

  2. プランに必要な作業量を定量化する選択したプランの値は、 非アクティブ なエントリの と比較されます。選択したプランの 値が次の場合:

    • 非アクティブ なエントリの値以下の場合

      選択したプランはプレースホルダーの非アクティブなエントリを置き換え、アクティブ状態になります。

      置換が行われる前に、非アクティブなエントリがアクティブになった場合(たとえば、別のクエリ操作のため)、新しくアクティブになったエントリは、プランに必要な作業量を定量化する値が選択したプランより大きい場合にのみ置換されます。

    • 非アクティブ なエントリの より大きい場合
      非アクティブなエントリは残りますが、プランに必要な作業量を定量化する値は増加します。

キャッシュ内のエントリは勝者プランのものですプランナーはこのエントリを使用してクエリプランを生成できます。

クエリで、シェイプのキャッシュ エントリの状態がアクティブの場合、以下のようになります。

アクティブなエントリはクエリプランの生成に使用されます。

プランナーはエントリのパフォーマンスも評価し、プランに必要な作業量を定量化する値が選択基準を満たさなくなった場合は、非アクティブ状態に移行します。

プラン キャッシュの変更をトリガーする追加のシナリオについては、「プラン キャッシュのフラッシュ」を参照してください。

特定のクエリのクエリプラン情報を表示するには、 db.collection.explain() または cursor.explain() を使用します。

コレクションのプラン キャッシュ情報を表示するには、$planCacheStats 集計ステージを使用できます。

mongod が再起動またはシャットダウンした場合、クエリプランのキャッシュは保持されません。さらに、

  • すべての DDLイベントにより、関連するコレクションのプランキャッシュがクリアされます。DDL イベントの例には、コレクションを削除すること、インデックスの作成、削除すること、または非表示があります。

  • 最近の使用頻度が最も少ない(LRU)キャッシュを置換するメカニズムにより、状態に関係なく、最近のアクセス頻度が最も少なかったキャッシュ エントリーが消去されます。

ユーザーは次の操作も可能です。

  • PlanCache.clear() メソッドを使用してプラン キャッシュ全体を手動でクリアします。

  • PlanCache.clearPlansByQuery()メソッドを使用して、特定のプラン キャッシュのエントリを手動でクリアします。

MongoDB5.0 以降では、すべてのコレクションの plan cacheplan caches0の累積サイズが.5 GBより小さい場合にのみ、プランキャッシュは完全な エントリを保存します。すべてのコレクションの の累積サイズがこのしきい値を超えると、追加のplan caches plan cacheエントリは次のデバッグ情報なしで保存されます。

plan cache エントリの推定サイズ(バイト単位)は、$planCacheStats の出力に表示されます。

同じプランキャッシュクエリシェイプを持つ低速クエリを識別できるように、各プランキャッシュクエリシェイプはクエリ ハッシュに関連付けられています。 プランキャッシュクエリシェイプハッシュは、クエリシェイプのハッシュを表す 16 進数のstringであり、クエリシェイプのみに依存しクエリシェイプ。

注意

他のハッシュ関数と同様に、2 つの異なるクエリシェイプで同じハッシュ値が生成される場合があります。ただし、異なるクエリシェイプ間でハッシュ衝突が発生する可能性は低くなります。

MongoDB 8.0 以降では、既存の queryHashフィールドはplanCacheShapeHash という名前の新しいフィールドに重複します。 以前のバージョンのMongoDBを使用している場合は、queryHashフィールドのみが表示されます。 今後のMongoDBバージョンでは、非推奨の queryHashフィールドが排除されます。代わりに planCacheShapeHashフィールドを使用する必要があります。

クエリプランキャッシュに関する詳細なインサイトを提供するために、 MongoDB が提供されています。planCacheKey

planCacheKey は、プランキャッシュクエリシェイプのハッシュであり、そのシェイプで使用可能なインデックスによってさらに区別されます。

注意

planCacheShapeHash とは異なり、planCacheKey は、クエリシェイプとそのシェイプで現在使用可能なインデックスの両方の関数です。つまり、クエリシェイプのサポートが可能なインデックスが追加または削除された場合、planCacheKey 値は変わる可能性がありますが、planCacheShapeHash の値は変化しません。

MongoDB 8.0 以降では、既存の queryHashフィールドはplanCacheShapeHash という名前の新しいフィールドに重複します。 以前のバージョンのMongoDBを使用している場合は、queryHashフィールドのみが表示されます。 今後のMongoDBバージョンでは、非推奨の queryHashフィールドが排除されます。代わりに planCacheShapeHashフィールドを使用する必要があります。

たとえば、次のインデックスを持つコレクション foo を考えます。

db.foo.createIndex( { x: 1 } )
db.foo.createIndex( { x: 1, y: 1 } )
db.foo.createIndex( { x: 1, z: 1 }, { partialFilterExpression: { x: { $gt: 10 } } } )

このコレクションに対する次のクエリは、同じシェイプです。

db.foo.explain().find( { x: { $gt: 5 } } ) // Query Operation 1
db.foo.explain().find( { x: { $gt: 20 } } ) // Query Operation 2

このようなクエリがある場合、部分フィルター式を含むインデックスはクエリ操作 2 をサポートできますが、クエリ操作 1 はサポートしません。クエリ操作 1 をサポートするために使用できるインデックスはクエリ操作 2 とは異なるため、2 つのクエリの planCacheKey は異なります。

いずれかのインデックスが削除された場合、または新しいインデックス { x: 1, a: 1 } が追加された場合、両方のクエリ操作の planCacheKey が変更されます。

planCacheShapeHashplanCacheKey は以下で利用可能です。

インデックス フィルターは planCacheSetFilter コマンドで設定され、クエリシェイプについてどのインデックスがプランナーに評価されるかを決定します。プランキャッシュクエリシェイプは、クエリ、並べ替え、およびプロジェクションの仕様の組み合わせで構成されます。特定のクエリ形状にインデックスフィルターが存在する場合、プランナーはフィルターで指定されたインデックスのみを考慮します。

プランキャッシュクエリシェイプのインデックスフィルターが存在する場合、MongoDB は hint() を無視します。MongoDB がクエリシェイプにインデックス フィルターを適用したかどうかを確認するには、db.collection.explain() メソッドまたは cursor.explain() メソッドの indexFilterSet フィールドを確認します。

インデックス フィルターは、プランナーによって評価されるインデックスのみに関係します。プランナーは、特定のプランキャッシュクエリシェイプの最適なプランとしてコレクションスキャンを選択することもできます。

インデックス フィルターは、サーバープロセスの実行中のみ存在し、シャットダウン後は保持されません。MongoDB には、フィルターを手動で削除するコマンドも用意されています。

インデックス フィルターは hint() メソッドと同様に、プランナーに期待される動作をオーバーライドするため、インデックス フィルターの使用は控えめにしてください。

MongoDB 6.0 以降、インデックス フィルターは、以前はplanCacheSetFilter コマンドを使用して設定されていた照合を使用します。

MongoDB8.0 以降では、インデックスフィルターを追加する代わりに クエリ設定を使用します 。 MongoDB. 以降、インデックス8 0フィルターは非推奨です。

クエリ設定は、インデックス フィルターよりも多くの機能を持ちます。 また、インデックス フィルターは永続的ではなく、すべてのクラスター ノードに対してインデックス フィルターを簡単に作成することはできません。 クエリ設定を追加して例を探すには、 setQuerySettingsを参照してください。

ルール バッジを取得する

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

詳細