# 画面設計書 156-プランキャッシュ

## 概要

本ドキュメントは、dbatools PowerShellモジュールにおけるプランキャッシュ管理機能の設計を定義する。SQL Serverのプランキャッシュ使用状況を分析し、シングルユースプランによるメモリ浪費を特定・解消するための機能群を提供する。

### 本画面の処理概要

本機能は、sys.dm_exec_cached_plansを照会してシングルユースのアドホック・プリペアドステートメントによるプランキャッシュ使用量を分析し、必要に応じてプランキャッシュをクリアする。

**業務上の目的・背景**：動的SQLを多用するアプリケーションでは、パラメータ化されていない各クエリが個別の実行プランを生成し、これらのシングルユースプランがメモリを浪費する。本機能は、Kimberly L. Trippの手法に基づき、シングルユースプランによるキャッシュ肥大化を検出し、閾値を超えた場合に自動的にプランキャッシュをクリアできる。100MB以上のシングルユースプランが検出された場合は、「Optimize for Ad Hoc Workloads」の有効化を検討すべき。

**画面へのアクセス方法**：PowerShellコンソールまたはスクリプトから以下のコマンドを実行してアクセスする：
- `Get-DbaPlanCache -SqlInstance <インスタンス名>` - プランキャッシュ使用状況取得
- `Clear-DbaPlanCache -SqlInstance <インスタンス名>` - プランキャッシュクリア

**主要な操作・処理内容**：
1. sys.dm_exec_cached_plansからシングルユースプランの統計取得
2. usecounts = 1 かつ objtype IN ('Adhoc', 'Prepared') のプランをカウント
3. シングルユースプランの合計サイズ（MB）を計算
4. 閾値（デフォルト100MB）を超えた場合にDBCC FREESYSTEMCACHEを実行
5. クリア結果のレポート出力

**画面遷移**：
- Get-DbaPlanCacheの出力をパイプラインでClear-DbaPlanCacheに渡すことが可能
- Find-DbaInstanceと連携して複数インスタンスを処理可能

**権限による表示制御**：
- SQL Server接続権限が必要
- DBCC FREESYSTEMCACHE実行にはALTER SERVER STATE権限が必要

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 411 | Get-DbaPlanCache | 主機能 | シングルユースプランキャッシュ使用状況取得 |
| 402 | Clear-DbaPlanCache | 補助機能 | プランキャッシュのクリア |

## 画面種別

一覧 / 診断情報表示 / 操作実行

## URL/ルーティング

PowerShellコマンドレット:
- `Get-DbaPlanCache`
- `Clear-DbaPlanCache`

## 入出力項目

### Get-DbaPlanCache パラメータ

| パラメータ名 | 型 | 必須 | 説明 |
|-------------|------|------|------|
| SqlInstance | DbaInstanceParameter[] | Yes | 接続先SQL Serverインスタンス |
| SqlCredential | PSCredential | No | SQL Server認証用資格情報 |
| EnableException | switch | No | 例外処理の有効化 |

### Clear-DbaPlanCache パラメータ

| パラメータ名 | 型 | 必須 | 説明 |
|-------------|------|------|------|
| SqlInstance | DbaInstanceParameter[] | No | 接続先SQL Serverインスタンス |
| SqlCredential | PSCredential | No | SQL Server認証用資格情報 |
| Threshold | int | No | クリア閾値（MB、デフォルト: 100） |
| InputObject | object[] | No | パイプライン入力（Get-DbaPlanCacheから） |
| EnableException | switch | No | 例外処理の有効化 |
| WhatIf | switch | No | 実行せずに結果を確認 |
| Confirm | switch | No | 実行前に確認 |

## 表示項目

### Get-DbaPlanCache 出力プロパティ

| プロパティ名 | 型 | 説明 |
|-------------|------|------|
| ComputerName | string | SQL Serverインスタンスのコンピュータ名 |
| InstanceName | string | SQL Serverインスタンス名 |
| SqlInstance | string | 完全なSQL Serverインスタンス名 |
| Size | dbasize | シングルユースプランの合計サイズ |
| UseCount | int | シングルユースプランの数 |

### Clear-DbaPlanCache 出力プロパティ

| プロパティ名 | 型 | 説明 |
|-------------|------|------|
| ComputerName | string | SQL Serverインスタンスのコンピュータ名 |
| InstanceName | string | SQL Serverインスタンス名 |
| SqlInstance | string | 完全なSQL Serverインスタンス名 |
| Size | dbasize | クリア前のシングルユースプランサイズ |
| Status | string | 処理結果（"Plan cache cleared" または "Plan cache size below threshold"） |

## イベント仕様

### 1-Get-DbaPlanCache実行

1. Connect-DbaInstanceでSQL Serverインスタンスに接続
2. sys.dm_exec_cached_plansに対するクエリを実行
3. usecounts = 1 かつ objtype IN ('Adhoc', 'Prepared') でフィルタ
4. サイズ合計（MB）とカウントを集計
5. dbasizeオブジェクトに変換して出力

### 2-Clear-DbaPlanCache実行

1. SqlInstanceまたはInputObjectからプランキャッシュ情報を取得
2. シングルユースプランサイズとThresholdを比較
3. 閾値以上の場合：
   - Connect-DbaInstanceでSQL Serverインスタンスに接続
   - DBCC FREESYSTEMCACHE('SQL Plans') を実行
   - "Plan cache cleared" ステータスで結果出力
4. 閾値未満の場合：
   - "Plan cache size below threshold" ステータスで結果出力

## データベース更新仕様

### 操作別データベース影響一覧

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| Get-DbaPlanCache | sys.dm_exec_cached_plans | SELECT | プランキャッシュ統計取得 |
| Clear-DbaPlanCache | プランキャッシュ | DBCC | プランキャッシュクリア |

### テーブル別更新項目詳細

#### Clear-DbaPlanCache - プランキャッシュ

| 操作 | 項目 | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DBCC FREESYSTEMCACHE | 'SQL Plans' | すべてのSQLプランをクリア | プラン再コンパイルが発生 |

## メッセージ仕様

| メッセージID | レベル | 条件 | メッセージ内容 |
|-------------|--------|------|---------------|
| - | Error | 接続失敗 | "Failure" |
| - | Verbose | 閾値未満 | "Plan cache size below threshold ({Threshold})" |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| SQL Server接続失敗 | ConnectionError カテゴリでStop-Function実行、処理継続 |

## 備考

- シングルユースプランは usecounts = 1 AND objtype IN ('Adhoc', 'Prepared') で識別
- 100MB以上のシングルユースプランがある場合は「Optimize for Ad Hoc Workloads」の有効化を推奨
- Clear-DbaPlanCacheはSupportsShouldProcessをサポート（-WhatIf, -Confirm）
- パイプラインでFind-DbaInstance | Get-DbaPlanCache | Clear-DbaPlanCacheの連携が可能
- 参考資料:
  - https://www.sqlskills.com/blogs/kimberly/plan-cache-adhoc-workloads-and-clearing-the-single-use-plan-cache-bloat/

---

## コードリーディングガイド

本画面を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

プランキャッシュ情報のデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Get-DbaPlanCache.ps1 | `public/Get-DbaPlanCache.ps1` | 74-78行目: SQLクエリ定義 |
| 1-2 | Get-DbaPlanCache.ps1 | `public/Get-DbaPlanCache.ps1` | 90-93行目: dbasizeへの変換と出力 |

**読解のコツ**: MB単位で取得したサイズを1024*1024倍してバイトに変換後、dbasizeオブジェクトに。

#### Step 2: エントリーポイントを理解する

処理の起点となるコマンドレット関数を特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Get-DbaPlanCache.ps1 | `public/Get-DbaPlanCache.ps1` | 66-72行目: param()ブロック |
| 2-2 | Clear-DbaPlanCache.ps1 | `public/Clear-DbaPlanCache.ps1` | 82-90行目: param()ブロック |

**主要処理フロー (Get-DbaPlanCache)**:
1. **82-87行目**: Connect-DbaInstanceでSQL Server接続
2. **89行目**: Server.Query()でSQLクエリ実行
3. **90行目**: MB→bytesへの変換
4. **91行目**: dbasizeオブジェクト追加
5. **93行目**: Select-DefaultViewで出力

#### Step 3: Clear-DbaPlanCache処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Clear-DbaPlanCache.ps1 | `public/Clear-DbaPlanCache.ps1` | 91-127行目: process ブロック全体 |

**主要処理フロー**:
- **92-94行目**: SqlInstanceからGet-DbaPlanCacheでInputObject取得
- **96-113行目**: 閾値以上の場合のクリア処理
- **105行目**: DBCC FREESYSTEMCACHE('SQL Plans')実行
- **114-124行目**: 閾値未満の場合のスキップ処理

### プログラム呼び出し階層図

```
Get-DbaPlanCache
    |
    +-- Connect-DbaInstance
    |       +-- SMO Server Object生成
    |
    +-- Server.Query()
    |       +-- sys.dm_exec_cached_plans集計
    |
    +-- [dbasize]変換
    |
    +-- Select-DefaultView

Clear-DbaPlanCache
    |
    +-- Get-DbaPlanCache (SqlInstance指定時)
    |       +-- (上記と同じ)
    |
    +-- InputObject (パイプライン入力時)
    |
    +-- 閾値比較
    |       |
    |       +-- [閾値以上]
    |       |       +-- Connect-DbaInstance
    |       |       +-- Server.Query("DBCC FREESYSTEMCACHE('SQL Plans')")
    |       |       +-- Status: "Plan cache cleared"
    |       |
    |       +-- [閾値未満]
    |               +-- Status: "Plan cache size below threshold"
    |
    +-- PSCustomObject出力
```

### データフロー図

```
[入力]                    [処理]                         [出力]

SqlInstance    ------>  Connect-DbaInstance  ----+
                                                 |
SqlCredential  ------>                           |
                                                 v
                        Server.Query()       --> dm_exec_cached_plans
                             |                       |
                             v                       v
                        SUM(size_in_bytes)      COUNT(*)
                        WHERE usecounts=1       WHERE objtype IN (...)
                             |                       |
                             v                       v
                        MB / 1024 / 1024   -->  [dbasize] Size
                                                     |
                                                     v
                                                PSCustomObject
                                                     |
          +---------<------ パイプライン ------<-----+
          |
          v
    Clear-DbaPlanCache
          |
          +-- Threshold比較 (デフォルト: 100MB)
          |       |
          |       +-- [>=] DBCC FREESYSTEMCACHE
          |       +-- [<] スキップ
          |
          v
    PSCustomObject (Status含む)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Get-DbaPlanCache.ps1 | `public/Get-DbaPlanCache.ps1` | ソース | プランキャッシュ統計取得 |
| Clear-DbaPlanCache.ps1 | `public/Clear-DbaPlanCache.ps1` | ソース | プランキャッシュクリア |
| Connect-DbaInstance.ps1 | `public/Connect-DbaInstance.ps1` | ソース | SQL Server接続処理 |
