クエリプラン
MongoDB クエリ プランナーは、どのクエリに対しても、使用可能なインデックスを考慮して最も効率的なクエリプランを選択し、キャッシュします。クエリプランの効率性を評価するために、クエリ プランナーはすべての候補プランを試用期間中に実行します。一般的に、選出されるプランは、試用期間中に実行する作業量が最も少なく、最も多くの結果が得られるクエリプランです。
関連付けられているプランキャッシュエントリは、同じプランキャッシュクエリシェイプを持つ後続のクエリに使用されます。
以下の図はクエリプランナーのロジックを示しています。
注意
explain
を使用すると、既存のすべてのプラン キャッシュ エントリが無視され、MongoDB クエリ プランナーが新しいプラン キャッシュ エントリを作成できなくなります。
プラン キャッシュ エントリの状態
各プラン キャッシュ クエリシェイプは、キャッシュ内の次の 3 つの状態のうちのいずれか 1 つに関連付けられています。
状態 | 説明 |
---|---|
キャッシュ内のエントリは、このシェイプのプレースホルダー エントリです。つまり、プランナーはシェイプを参照して、プランに必要な作業量を定量化する値を計算し、シェイププレースホルダーエントリを保存しましたが、プランキャッシュクエリシェイプはクエリプランの生成には使用されません。 クエリの場合、シェイプのキャッシュエントリ状態が 非アクティブ な場合、次のようになります。
| |
キャッシュ内のエントリは勝者プランのものですプランナーはこのエントリを使用してクエリプランを生成できます。 クエリの場合、シェイプのキャッシュエントリ状態が アクティブ の場合、次のようになります。 アクティブなエントリはクエリプランの生成に使用されます。 プランナーはエントリのパフォーマンスも評価し、プランに必要な作業量を定量化する値が選択基準を満たさなくなった場合は、 非アクティブ 状態に移行します。 |
プラン キャッシュ の変更をトリガーする追加のシナリオについては、「 プランキャッシュのフラッシュ 」を参照してください。
クエリプランとキャッシュ情報
特定のクエリのクエリプラン情報を表示するには、 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
の出力に表示されます。
planCacheShapeHash と planCacheKey
planCacheShapeHash
同じプランキャッシュクエリシェイプを持つ低速クエリを識別できるように、各プランキャッシュクエリシェイプはクエリ ハッシュに関連付けられています。 プランキャッシュクエリシェイプハッシュは、クエリシェイプのハッシュを表す 16 進数のstringであり、クエリシェイプのみに依存しクエリシェイプ。
注意
他のハッシュ関数と同様に、2 つの異なるクエリシェイプで同じハッシュ値が生成される場合があります。ただし、異なるクエリシェイプ間でハッシュ衝突が発生する可能性は低くなります。
MongoDB 8.0以降、既存のqueryHash
フィールドの名前がplanCacheShapeHash
に変更されます。 以前のバージョンの MongoDB を使用している場合は、 planCacheShapeHash
ではなくqueryHash
が表示されます。
planCacheKey
クエリプラン キャッシュに関する詳細なインサイトを提供するために、MongoDB ではplanCacheKey
が提供されています。
planCacheKey
は、クエリに関連付けられたプラン キャッシュ エントリのキーのハッシュです。
注意
planCacheShapeHash
とは異なり、planCacheKey
は、クエリシェイプとそのシェイプで現在使用可能なインデックスの両方の関数です。つまり、クエリシェイプのサポートが可能なインデックスが追加または削除された場合、planCacheKey
値は変わる可能性がありますが、planCacheShapeHash
の値は変化しません。
MongoDB 8.0以降、既存のqueryHash
フィールドの名前がplanCacheShapeHash
に変更されます。 以前のバージョンの MongoDB を使用している場合は、 planCacheShapeHash
ではなくqueryHash
が表示されます。
たとえば、次のインデックスを持つコレクション 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
が変更されます。
可用性
planCacheShapeHash
と planCacheKey
は以下で利用可能です。
explain() 出力フィールド:
MongoDB 8.0以降、既存の
queryHash
フィールドの名前がplanCacheShapeHash
に変更されます。 以前のバージョンの MongoDB を使用している場合は、planCacheShapeHash
ではなくqueryHash
が表示されます。遅いクエリをログに記録するときのプロファイラー ログ メッセージと診断ログ メッセージ(mongod および mongos ログ メッセージ) 。
$planCacheStats
集計ステージPlanCache.listQueryShapes()
メソッドとplanCacheListQueryShapes
コマンドPlanCache.getPlansByQuery()
メソッドとplanCacheListPlans
コマンド
インデックス フィルター
インデックス フィルターは planCacheSetFilter
コマンドで設定され、クエリシェイプについてどのインデックスがプランナーに評価されるかを決定します。プランキャッシュクエリシェイプは、クエリ、並べ替え、およびプロジェクションの仕様の組み合わせで構成されます。特定のクエリ形状にインデックスフィルターが存在する場合、プランナーはフィルターで指定されたインデックスのみを考慮します。
プランキャッシュクエリシェイプのインデックスフィルターが存在する場合、MongoDB は hint()
を無視します。MongoDB がクエリシェイプにインデックス フィルターを適用したかどうかを確認するには、db.collection.explain()
メソッドまたは cursor.explain()
メソッドの indexFilterSet
フィールドを確認します。
インデックス フィルターは、プランナーによって評価されるインデックスのみに関係します。プランナーは、特定のプランキャッシュクエリシェイプの最適なプランとしてコレクションスキャンを選択することもできます。
インデックス フィルターは、サーバープロセスの実行中のみ存在し、シャットダウン後は保持されません。MongoDB には、フィルターを手動で削除するコマンドも用意されています。
インデックス フィルターは hint()
メソッドと同様に、プランナーに期待される動作をオーバーライドするため、インデックス フィルターの使用は控えめにしてください。
MongoDB 6.0 以降、インデックス フィルターは、以前はplanCacheSetFilter
コマンドを使用して設定されていた照合を使用します。
MongoDB 8.0 以降では、インデックスフィルターを追加する代わりにクエリ設定を使用します。インデックス フィルターは MongoDB 8.0 以降、非推奨になっています。
クエリ設定は、インデックス フィルターよりも多くの機能を持ちます。 また、インデックス フィルターは永続的ではなく、すべてのクラスター ノードに対してインデックス フィルターを簡単に作成することはできません。 クエリ設定を追加して例を探すには、 setQuerySettings
を参照してください。