

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# キャッシュフィルターの計画
<a name="plan-cache-filter"></a>

インデックスフィルターとも呼ばれるプランキャッシュフィルターは、クエリプランナーが特定のクエリシェイプについて考慮できるインデックスのセットを制限します。クエリがフィルターを持つシェイプと一致する場合、プランナーはコレクション上のすべてのインデックスを評価するのではなく、そのフィルター内の という名前のインデックスからのみプランを選択します。

クエリシェイプは、クエリ述語、ソート仕様、コレクション名前空間の組み合わせで、述語値が正規化されます。値のみが異なる 2 つのクエリはシェイプを共有するため、1 つのフィルターですべてのクエリをカバーします。の出力では`planCacheListFilters`、正規化された値は として表示されます`"@"`。

プランキャッシュフィルターを使用すると、プランを固定できるため、データ分散やインデックスの変更によるインデックスの選択が遅くなるのを回避できます。フィルターには次のプロパティがあります。
+ **アプリケーションの変更は必要ありません。**フィルタはデータベースコマンドで設定され、サーバーに適用されるため、コードのデプロイなしでリグレッションを軽減できます。これは、すべての通話サイトに追加`hint`する必要がある との主な違いです。
+ **スコープは 1 つのクエリシェイプです。**シェイプは、完全なクエリではなく、コレクション、述語、ソートによって定義されるため、フィルターはそのシェイプに一致するクエリのみを制限します。同じコレクションに対する他のクエリは、引き続き通常どおり計画されます。
+ **変更は耐久性があります。**フィルターは、インスタンスの再起動とエンジンのパッチ適用全体で保持されます。コレクションを削除すると、そのフィルターが削除されます。
+ **変更は元に戻されます。**フィルターをクリアするとシェイプが通常のコストベースの計画に戻るため、フィルターは根本的な原因を調査しながらワークロードを安定させる低リスクの方法です。

**Topics**
+ [サポートされているコマンド](#plan-cache-filter-support)
+ [サポートされているクエリシェイプ](#plan-cache-filter-shapes)
+ [フィルターの設定、一覧表示、クリア](#plan-cache-filter-api)
+ [フィルターが適用されていることを確認する](#plan-cache-filter-explain)
+ [例](#plan-cache-filter-examples)
+ [ヒントとインデックスの変更を含む動作](#plan-cache-filter-behavior)

## サポートされているコマンド
<a name="plan-cache-filter-support"></a>

プランキャッシュフィルターには、プランナーバージョン 2.0 以降が必要です。フィルターを適用できるコマンドは、次の表に示すように、プランナーバージョンと Amazon DocumentDB マイナーバージョンによって異なります。


**プランキャッシュフィルターのコマンドサポート**  

| コマンド | プランナーの最小バージョン | 最小マイナーバージョン | 
| --- | --- | --- | 
| `find` | 2.0 | 5.0.0、8.0.0 | 
| `count` | 2.0 | 5.0.0、8.0.0 | 
| `update` | 2.0 | 5.0.2、8.0.2 | 
| `delete` | 2.0 | 5.0.2、8.0.2 | 
| `findAndModify` | 2.0 | 5.0.2、8.0.2 | 
| `distinct` | 3.0 | 8.0.0 | 
| `aggregate` | 3.0 | 8.0.2 | 

**注記**  
プランナーバージョン 3.0 は Amazon DocumentDB 8.0 でのみ使用できます。コマンド`distinct`と `aggregate` コマンドにはプランナーバージョン 3.0 が必要なため、これら 2 つのコマンドの計画キャッシュフィルターは Amazon DocumentDB 8.0 でのみ使用できます。プランナーバージョン 2.0 をサポートする Amazon DocumentDB 5.0 では、フィルターは `find`、、`count`、`delete`、`update`および `findAndModify` コマンドに適用されます。

`aggregate` コマンドの場合、シェイプはパイプラインの前面から取得されます。先頭はフィルター`$match`を提供し、先頭はソートを提供する`$sort`直後に を提供します。 `$skip` と はシェイプに影響を与え`$limit`ず、それ以降のステージも影響を受けません。

Amazon DocumentDB は、パイプラインを計画する前に最適化し、計画キャッシュフィルターは最適化されたパイプラインと照合されます。したがって、プランナーに表示されるフィルターとソートは、作成したステージとは異なる可能性があります。たとえば、パイプラインの前面にある 2 つの隣接する`$match`ステージが 1 つの`$and`述語に結合されます。

```
db.orders.aggregate([
  { $match: { status: "SHIPPED" } },
  { $match: { region: "us-east-1" } },
  { $group: { _id: "$customerId", total: { $sum: "$amount" } } }
])
```

プランナーは `$match`に 1 つ表示されるため`{$and: [{status: ...}, {region: ...}]}`、フィルターはその結合述語に設定する必要があります。

```
db.runCommand({planCacheSetFilter: "orders",
query: { $and: [ { status: "SHIPPED" }, { region: "us-east-1" } ] },
indexes: [ "status_1_region_1" ]})
```

`$lookup` ステージまたは `$graphLookup`ステージの外部コレクションに設定されたフィルターは、その外部コレクションのスキャンに使用されるインデックスを駆動します。

## サポートされているクエリシェイプ
<a name="plan-cache-filter-shapes"></a>

Amazon DocumentDB 5.0.2 および 8.0.2 以降では、プランキャッシュフィルターを持つクエリシェイプに次の演算子を表示できます。
+ `$text`。 検索文字列は正規化されるため、検索する用語だけが異なるクエリは 1 つのシェイプを共有します。
+ 「`$near`」および「`$nearSphere`」。どちらの演算子も同じ形状に正規化されます。座標、`$minDistance`、 `$maxDistance`はシェイプの一部ではありません。
+ 「`$geoWithin`」および「`$geoIntersects`」。GeoJSON ジオメトリタイプはシェイプの一部であるため、`Polygon`クエリと`MultiPolygon`クエリは異なるシェイプです。座標はシェイプの一部ではありません。
+ `$regex`、 フィールドで直接使用する場合。パターンとオプションは正規化されるため、同じフィールドのすべての正規表現は 1 つのシェイプを共有します。

`$jsonSchema`、、`$expr`または を使用するクエリシェイプのフィルターの設定はエラーコード 303 で失敗します`$sampleRate`。また、次のシェイプでも失敗します。これらのいずれかを使用するクエリは、フィルターなしで計画されます。
+ 、`$in`、`$nin`または 内に`$regex`ネストされた `$all`。正規表現とリテラル値を混在させる配列はインデックスに対して評価できないため、そのシェイプのフィルターを適用することはできません。
+ のソート仕様`{$natural: 1}`。`$natural` ソートはコレクションスキャンをリクエストしますが、プランナーをインデックスに制限することはできません。

## フィルターの設定、一覧表示、クリア
<a name="plan-cache-filter-api"></a>

計画キャッシュフィルターを設定するには、 `planCacheSetFilter` コマンドを使用します。`query` フィールドと `sort`フィールドは一緒にクエリシェイプを指定し、プランナーがそのシェイプについて考慮できるインデックス名を`indexes`一覧表示します。

```
db.runCommand({
planCacheSetFilter: <collection>,
query: <query>,
sort: <sort>, // optional
indexes: [ <index1>, <index2>, ...],
comment: <any> // optional
})
```

たとえば、次のコマンドは、プランナーをソート`{a: {$eq: "@"}, b: {$eq: "@"}}`なしでシェイプの`a_1`インデックスに制限します。

```
db.runCommand({planCacheSetFilter: "foo",
query: { a: 1, b: 1 },
sort: {},
indexes: [ "a_1" ]})
```

既にあるシェイプのフィルターを設定すると、既存のフィルターが置き換えられます。次の 2 つのコマンドを実行した後、シェイプのフィルター`{a: {$eq: "@"}, b: {$eq: "@"}}`は になります`["b_1"]`。

```
db.runCommand({planCacheSetFilter: "foo",
query: { a: 1, b: 1 },
sort: {},
indexes: [ "a_1" ]})

db.runCommand({planCacheSetFilter: "foo",
query: { a: 6, b: 10 },
sort: {},
indexes: [ "b_1" ]})
```

コレクション上のすべてのフィルターを一覧表示するには、 `planCacheListFilters` コマンドを使用します。

```
db.runCommand({planCacheListFilters: <collection>})
```

出力には、保存された各シェイプとその正規化された値と許可されたインデックスリストが表示されます。

```
{
"filters" : [
{
"query" : { "a" : { "$eq" : "@" } },
"sort" : { },
"indexes" : [ "a_1" ]
},
{
"query" : { "a" : { "$gt" : "@" } },
"sort" : { "a" : 1 },
"indexes" : [ "a_1_b_1" ]
}
],
"ok" : 1
}
```

演算子は保持され、値のみが に置き換えられます`"@"`。などの暗黙的な等価性`{a: 1}`は、明示的な形式でリストされ`{"a": {"$eq": "@"}}`、`$in`配列の要素は全体として として置き換えられます`{"a": {"$in": "@"}}`。ソートのないフィルターセットは、空の`sort`ドキュメントとともに一覧表示されます。

フィルターを削除するには、 `planCacheClearFilters` コマンドを使用します。

```
db.runCommand({
planCacheClearFilters: <collection>,
query: <query pattern>, // optional
sort: <sort specification>, // optional
comment: <any> // optional
})
```

コレクション上のすべてのフィルターをクリアするには、 `query`と の両方を省略します`sort`。

```
db.runCommand({planCacheClearFilters: "foo"})
```

`query` と の両方を指定すると、その正確なソートを持つフィルターのみが`sort`クリアされます。の値は`query`正規化されないため、代表的な値はすべて機能します。ソートなしで設定されたフィルターのみをクリアするには、空の`sort`ドキュメントを渡します。

```
db.runCommand({planCacheClearFilters: "foo", query: {a: 1}, sort: {a: 1}})

db.runCommand({planCacheClearFilters: "foo", query: {a: 1}, sort: {}})
```

## フィルターが適用されていることを確認する
<a name="plan-cache-filter-explain"></a>

`explain` 出力には、プランキャッシュフィルターのステータスを報告する 2 つのフィールドが含まれます。
+ `indexFilterSet` は、クエリの形状のコレクションにフィルターが存在する`true`場合です。
+ `indexFilterApplied` は、そのフィルターのリストからインデックスを使用してクエリが計画された`true`場合にのみ発生します。

Amazon DocumentDB 5.0.2 および 8.0.2 以降、これらのフィールドは、プランキャッシュフィルターをサポートするすべてのコマンドと、それらのコマンドのプロファイラー出力でレポートされます。以前のマイナーバージョンでは、これらは `find` コマンドに対してのみ報告されました。explain 出力の読み取りの詳細については、「」を参照してください[クエリプラン分析](performance-query-plan-analysis.md)。

フィルターは、適用せずにクエリシェイプを一致させることができます。フィルターのリスト内のインデックスのいずれもクエリを処理できない場合、プランナーはフィルターなしで再計画し、コストに関するインデックスを選択します。この場合、 `indexFilterSet`は `true`で、 `indexFilterApplied`は です`false`。これは、名前付きインデックスがクエリのフィールドをカバーしない場合、名前付きインデックスが存在しない場合、または`$regex`シェイプがアンカーされていないパターンや大文字と小文字を区別しないパターンなどのインデックス境界を生成できない場合に発生します。

## 例
<a name="plan-cache-filter-examples"></a>

次の例では、 `orders`コレクションと、これらのインデックスを持つ `$lookup` `customers`コレクションを使用しています。

```
db.orders.createIndex({ status: 1 })                         // status_1
db.orders.createIndex({ status: 1, orderDate: 1 })           // status_1_orderDate_1
db.orders.createIndex({ customerId: 1 })                     // customerId_1
db.customers.createIndex({ customerId: 1 })                  // customerId_1
```

### 例: `find`クエリを複合インデックスに固定する
<a name="plan-cache-filter-example-find"></a>

でフィルタリング`status`し、 でソートするクエリを考えてみましょう`orderDate`。

```
db.orders.find({ status: "SHIPPED" }).sort({ orderDate: 1 })
```

複合インデックスは述語とソートの両方`status_1_orderDate_1`を満たすため、個別のソートは必要ありません。プランナーが代わりに を選択した場合`status_1`、クエリは結果をソートする必要があります。これによりステージが追加され、一致する注文の数が増える`SORT`につれてコストが高くなります。プランナーをこのシェイプの複合インデックスに制限するには:

```
db.runCommand({planCacheSetFilter: "orders",
query: { status: "SHIPPED" },
sort: { orderDate: 1 },
indexes: [ "status_1_orderDate_1" ]})
```

値はシェイプから正規化されるため、この 1 つのフィルターは `{ status: "PENDING" }`、`{ status: "CANCELLED" }`、および同じソート`status`で の他のすべての値もカバーします。同じ述語を別のソートでカバーしたり、別のシェイプであるソートなしでカバーしたりすることはありません。でフィルターが有効になったことを確認します`explain`。

```
db.orders.find({ status: "SHIPPED" }).sort({ orderDate: 1 }).explain()
```

出力は `indexFilterSet: true`と を報告し`indexFilterApplied: true`、`IXSCAN`ステージ名は です`status_1_orderDate_1`。

### 例: を選択的インデックス`update`に固定する
<a name="plan-cache-filter-example-update"></a>

更新は、書き込む前に変更するドキュメントを見つける必要があり、そのルックアップは読み取りと同じ方法でインデックスを使用します。述語を複数のインデックスで提供できる場合、プランナーが選択するインデックスによって、更新が検査するドキュメントの数が決まります。

```
db.orders.updateMany(
  { customerId: 4815, status: "PENDING" },
  { $set: { status: "CANCELLED" } }
)
```

`customerId_1` と の両方がこの述語を提供`status_1`できます。更新を に固定するには`customerId_1`:

```
db.runCommand({planCacheSetFilter: "orders",
query: { customerId: 4815, status: "PENDING" },
indexes: [ "customerId_1" ]})
```

書き込みコマンドのフィルタには、Amazon DocumentDB 5.0.2 または 8.0.2 とプランナーバージョン 2.0 以降が必要です。更新`explain`の を使用して検証します。

```
db.runCommand({explain: {update: "orders",
updates: [{ q: { customerId: 4815, status: "PENDING" },
             u: { $set: { status: "CANCELLED" } },
             multi: true }]}})
```

成功プランは、 `IXSCAN`上の よりも `UPDATE` ステージです`customerId_1`。シェイプには書き込みのタイプが含まれていないため、このクエリシェイプを使用する `delete`および `findAndModify` コマンドにも同じフィルターが適用されます。

### 例: `aggregate`パイプラインと`$lookup`外部コレクションを固定する
<a name="plan-cache-filter-example-aggregate"></a>

集計の場合、シェイプは先頭ステージと`$sort`直後の`$match`ステージから取得されます。`$group` や など、それを超えるステージ`$project`はシェイプの一部ではありません。

```
db.orders.aggregate([
  { $match: { status: "SHIPPED" } },
  { $group: { _id: "$customerId", total: { $sum: "$amount" } } }
])
```

`$match` 述語に設定されたフィルターは、 の読み取りに使用されるインデックスを駆動します`orders`。

```
db.runCommand({planCacheSetFilter: "orders",
query: { status: "SHIPPED" },
indexes: [ "status_1" ]})
```

フィルターは、 `$lookup`または `$graphLookup`ステージが結合するコレクションにも適用されます。フィルターは、パイプラインが実行されるコレクションではなく、外部コレクションに設定されます。次のパイプラインでは、 `orders`は外部コレクションで、 は外部コレクション`customers`です。

```
db.orders.aggregate([
  { $lookup: { from: "customers",
               localField: "customerId",
               foreignField: "customerId",
               as: "customer" } }
])
```

結合は外部ドキュメントごとに 1 `customers`回プローブされるため、そこで選択されたインデックスは繰り返し適用され、コストはパイプライン全体に乗算されます。そのスキャンを特定のインデックスに固定するには、結合キーの等価シェイプ`customers`のフィルターを に設定します。

```
db.runCommand({planCacheSetFilter: "customers",
query: { customerId: 1 },
indexes: [ "customerId_1" ]})
```

値はシェイプから正規化されるため、`1`上記の値はプレースホルダーであり、どの値でも同じフィルターが生成されます。外部コレクションフィルターが適用されると、最上位の `indexFilterSet`フィールドと `indexFilterApplied`フィールドは を報告し`true`、選択したフィルターのインデックスは、獲得プランの外部側に表示されます。のフィルターには、Amazon DocumentDB 8.0.2 とプランナーバージョン 3.0 `aggregate`が必要です。

## ヒントとインデックスの変更を含む動作
<a name="plan-cache-filter-behavior"></a>
+ プランキャッシュフィルターは、 よりも優先されます`hint`。Amazon DocumentDB は最初にフィルターを適用し、次にフィルターの許可されたインデックスリスト内にヒントを適用します。ヒントがフィルターが許可するインデックスに名前を付ける場合、そのインデックスが使用されます。ヒントがフィルターで許可されていないインデックスに名前を付けると、ヒントは無視され、プランナーは許可されたインデックスの中からコストに基づいて選択します。どちらのヒントフォームも、インデックスに名前を付けるかキーパターンを付けるかにかかわらず、同じように動作します。

  たとえば、コレクションにインデックス `a_1`、`b_1`、および `foo`があり`a_1_b_1`、インデックスリスト `{query: {a: {$eq: "@"}, b: {$eq: "@"}}, sort: {a: 1}}` を持つシェイプにフィルターを設定した場合`["a_1", "a_1_b_1"]`、 を実行すると `db.foo.find({ a: 10, b: 20 }).sort({a: 1}).hint({ a: 1 })`が使用されます。これは`a_1`、ヒントで名前が付けられ、フィルターで許可されているためです。
+ インデックスを削除しても、フィルターは変更されません。フィルターはインデックス名を保持します。そのインデックスが欠落している間、計画ではスキップされます。フィルターのリスト内の別のインデックスがクエリを処理できる場合でも、フィルターは引き続き適用されます。名前付きインデックスが利用できない場合にのみ、 が`indexFilterApplied`レポートします`false`。同じ名前のインデックスを再作成すると、再び対象になります。
+ コレクションを削除すると、そのコレクションのフィルターがすべて削除されます。