Docs Menu
Docs Home
/
MongoDBマニュアル
/ /

クエリプラン

項目一覧

  • プラン キャッシュ エントリの状態
  • planCacheShapeHash
  • planCacheKey
  • 可用性

MongoDB クエリ プランナーは、どのクエリに対しても、使用可能なインデックスを考慮して最も効率的なクエリプランを選択し、キャッシュします。クエリプランの効率性を評価するために、クエリ プランナーはすべての候補プランを試用期間中に実行します。一般的に、選出されるプランは、試用期間中に実行する作業量が最も少なく、最も多くの結果が得られるクエリプランです。

関連付けられているプランキャッシュエントリは、同じプランキャッシュクエリシェイプを持つ後続のクエリに使用されます。

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

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

注意

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

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

状態
説明

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

クエリの場合、プランキャッシュクエリシェイプのキャッシュエントリ状態が欠落している場合、次のようになります。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • インデックスやコレクションの削除などのカタログ操作により、プラン キャッシュが消去されます。

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

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

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

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

以下も参照してください。

MongoDB 5.0以降では、すべてのコレクションのplan cachesの累積サイズが0.5より小さい場合にのみ、プラン キャッシュは完全なplan cacheエントリを保存します。 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 コマンドを使用して設定されていた照合を使用します。

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

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

以下も参照してください。

戻る

書込みパフォーマンス