# 機能設計書 417-Test-DbaMaxMemory

## 概要

本ドキュメントは、OSメモリ圧迫を防ぎパフォーマンスを最適化するための推奨SQL Server最大メモリ設定を計算する`Test-DbaMaxMemory`機能の設計を定義する。

### 本機能の処理概要

本機能は、サーバーメモリとSQL Serverインスタンスを分析して、最適な最大メモリ構成設定を計算する。サーバーの合計メモリに基づいてオペレーティングシステム用に適切なメモリを予約する階層的アルゴリズムを使用し、複数のSQLインスタンスや他のSQLサービス（SSAS、SSRS、SSIS）を考慮する。

**業務上の目的・背景**：SQL Serverのデフォルト設定（2147483647 MB）のままでは、SQL Serverが利用可能なすべてのメモリを消費し、OSやその他のアプリケーションにメモリ圧迫を引き起こす。Jonathan Kehayias氏のメモリ計算手法に基づき、現在の最大メモリ設定と推奨値を比較することで、誤設定されたサーバーを特定できる。

**機能の利用シーン**：
- SQL Serverメモリ設定の監査
- 新規インスタンスの設定前の推奨値確認
- 複数インスタンス環境のメモリ配分計画
- Set-DbaMaxMemoryへのパイプライン入力

**主要な処理内容**：
1. 指定されたSQL Serverインスタンスへの接続
2. Get-DbaMaxMemoryで現在のメモリ設定を取得
3. Get-DbaServiceで実行中のSQLエンジンインスタンス数を取得
4. 階層的アルゴリズムで推奨値を計算
5. 結果をインスタンス数で按分

**関連システム・外部連携**：
- Get-DbaMaxMemory（現在値取得）
- Get-DbaService（インスタンス数検出）

**権限による制御**：VIEW SERVER STATE権限が必要

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | コマンドライン | 主画面 | PowerShellコンソールからの実行 |

## 機能種別

分析・計算処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| SqlInstance | DbaInstanceParameter[] | Yes | 対象SQL Serverインスタンス | パイプライン入力可能 |
| SqlCredential | PSCredential | No | SQL Server接続用代替資格情報 | Windows/SQL認証対応 |
| Credential | PSCredential | No | Windows管理用代替資格情報 | Get-DbaService用 |
| EnableException | switch | No | 例外の詳細表示有効化 | - |

### 入力データソース

- SQL Server: sys.configurations (max server memory)
- Windows: SQL Serverサービス情報

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 | デフォルト表示 |
|--------|-----|------|---------------|
| ComputerName | string | SQL Serverホストのコンピュータ名 | Yes |
| InstanceName | string | SQL Serverインスタンス名 | Yes |
| SqlInstance | string | 完全なSQL Serverインスタンス名 | Yes |
| InstanceCount | int | 検出されたSQLエンジンインスタンス数 | Yes |
| Total | int | サーバーの合計メモリ（MB） | Yes |
| MaxValue | int | 現在のMax Server Memory設定（MB） | Yes |
| RecommendedValue | int | 計算された推奨値（MB） | Yes |
| Server | SMO.Server | SMOサーバーオブジェクト | No |

### 出力先

PowerShellパイプライン(PSCustomObject)

## 処理フロー

### 処理シーケンス

```
1. processブロック: インスタンスごとの処理ループ
   └─ 1.1 Connect-DbaInstanceでサーバー接続
   └─ 1.2 Get-DbaMaxMemoryで現在のメモリ情報取得
   └─ 1.3 Get-DbaServiceで実行中インスタンス数を取得
   └─ 1.4 SSAS/SSRS/SSIS検出時は警告を出力
   └─ 1.5 階層的アルゴリズムで推奨値を計算
   └─ 1.6 インスタンス数で按分
   └─ 1.7 結果をPSCustomObjectとして出力
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{各SqlInstanceをループ}
    B --> C[Connect-DbaInstance]
    C --> D{接続成功?}
    D -->|No| E[Stop-Function/Continue]
    E --> B
    D -->|Yes| F[Get-DbaMaxMemory]
    F --> G{Linux/Mac?}
    G -->|Yes| H[InstanceCount=1 + Warning]
    G -->|No| I[Get-DbaService]
    I --> J[実行中Engineインスタンス数カウント]
    J --> K{InstanceCount=0?}
    K -->|Yes| L[InstanceCount=1 + Warning]
    K -->|No| M[SSAS/SSRS/SSIS検出チェック]
    H --> N{serverMemory null?}
    L --> M
    M --> N
    N -->|Yes| O[continue]
    N -->|No| P[reserve=1]
    P --> Q{totalMemory >= 4096?}
    Q -->|No| R[recommendedMax = total * 0.5]
    Q -->|Yes| S[階層計算ループ]
    S --> T{currentCount > 16384?}
    T -->|Yes| U[reserve += 1, currentCount -= 8192]
    T -->|No| V[reserve += 1, currentCount -= 4096]
    U --> W{currentCount/4096 > 0?}
    V --> W
    W -->|Yes| S
    W -->|No| X[recommendedMax = total - reserve*1024]
    X --> Y[recommendedMax /= instanceCount]
    R --> Y
    Y --> Z[PSCustomObject作成]
    Z --> AA[Select-DefaultView出力]
    AA --> B
    B -->|完了| BB[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | Linux/Macサポート | Linux/Macではインスタンス数検出不可、デフォルト1 | isLinux/isMacOS時 |
| BR-002 | インスタンス数デフォルト | 検出失敗時はインスタンス数=1 | 検出エラー時 |
| BR-003 | 他サービス警告 | SSAS/SSRS/SSIS検出時は計算が不正確である旨を警告 | サービス検出時 |
| BR-004 | 4GB未満サーバー | 4GB未満の場合は合計の50%を推奨 | totalMemory < 4096時 |

### 計算ロジック

Jonathan Kehayias氏のアルゴリズム：

```powershell
# 4GB以上の場合の階層的計算
$reserve = 1
$currentCount = $totalMemory
while ($currentCount / 4096 -gt 0) {
    if ($currentCount -gt 16384) {
        $reserve += 1
        $currentCount += -8192  # 16GB超は8GBごとに1GB予約
    } else {
        $reserve += 1
        $currentCount += -4096  # 16GB以下は4GBごとに1GB予約
    }
}
$recommendedMax = [int]($totalMemory - ($reserve * 1024))

# インスタンス数で按分
$recommendedMax = $recommendedMax / $instanceCount
```

## データベース操作仕様

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| メモリ設定取得 | sys.configurations | SELECT | max server memory設定 |

### テーブル別操作詳細

#### sys.configurations (via Get-DbaMaxMemory)

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | value_in_use | name='max server memory (MB)' | 現在値 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ConnectionError | 接続エラー | Connect-DbaInstance失敗 | Stop-FunctionでContinue |
| ServiceError | サービス検出エラー | Get-DbaService失敗 | Warning + InstanceCount=1 |

### リトライ仕様

リトライ処理なし（単一試行）

## トランザクション仕様

読み取り専用処理のためトランザクション管理不要

## パフォーマンス要件

- 単一インスタンスの計算は即時完了
- Get-DbaServiceによるリモートサービス検出に数秒かかる場合あり

## セキュリティ考慮事項

- VIEW SERVER STATE権限が必要（SQL Server）
- Windows管理権限が必要（Get-DbaService用、Credentialパラメータで指定可能）
- SQL認証/Windows認証/Azure AD認証に対応
- 資格情報はPSCredentialで安全に渡される

## 備考

- Jonathan Kehayias氏のメモリ計算手法に基づく
- 推奨値は「一般的な推奨事項」であり、環境固有の要因を考慮していない
- Chrissy LeMaire氏(@cl)による開発

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Test-DbaMaxMemory.ps1 | `public/Test-DbaMaxMemory.ps1` | 出力PSCustomObjectの構造（147-156行目） |

**読解のコツ**: Serverプロパティに接続済みSMOオブジェクトを含み、Set-DbaMaxMemoryへのパイプライン入力に使用される

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Test-DbaMaxMemory.ps1 | `public/Test-DbaMaxMemory.ps1` | パラメータ定義（72-78行目） |

**主要処理フロー**:
1. **73-74行目**: SqlInstanceパラメータ（必須、パイプライン入力可能）
2. **75行目**: SqlCredentialパラメータ（SQL Server用）
3. **76行目**: Credentialパラメータ（Windows管理用）

#### Step 3: インスタンス数検出を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Test-DbaMaxMemory.ps1 | `public/Test-DbaMaxMemory.ps1` | インスタンス数検出ロジック（90-119行目） |

**主要処理フロー**:
- **91-93行目**: Linux/Mac判定
- **96-100行目**: Get-DbaServiceでサービス情報取得
- **102行目**: Running状態のEngineインスタンスをカウント
- **109行目**: SSAS/SSRS/SSISの検出と警告

#### Step 4: 推奨値計算を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Test-DbaMaxMemory.ps1 | `public/Test-DbaMaxMemory.ps1` | 推奨値計算アルゴリズム（124-146行目） |

**主要処理フロー**:
- **124行目**: reserve=1（初期値）
- **129-139行目**: 階層計算ループ
- **132-134行目**: 16GB超は8GBごとに1GB予約
- **135-137行目**: 16GB以下は4GBごとに1GB予約
- **140行目**: recommendedMax = total - reserve*1024
- **141-143行目**: 4GB未満は50%
- **145行目**: インスタンス数で按分

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

```
Test-DbaMaxMemory
    │
    ├─ Connect-DbaInstance
    │      └─ SMO接続の確立
    │
    ├─ Get-DbaMaxMemory
    │      └─ 現在のmax server memory取得
    │
    ├─ Get-DbaService（Windows環境のみ）
    │      └─ 実行中SQLインスタンス検出
    │
    ├─ 推奨値計算
    │      ├─ 階層的メモリ予約計算
    │      └─ インスタンス数按分
    │
    └─ Select-DefaultView
           └─ 出力プロパティの選択
```

### データフロー図

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

SqlInstance ──────▶ Connect-DbaInstance ──────┐
                                              │
SqlCredential ────▶ 認証処理 ────────────────┘
                          │
                          ▼
                   Get-DbaMaxMemory
                          │
                          ├─ Total (合計メモリ)
                          └─ MaxValue (現在値)
                          │
Credential ───────▶ Get-DbaService ────────────┐
                          │                    │
                          ▼                    ▼
                   InstanceCount       SSAS/SSRS/SSIS検出
                          │                    │
                          │◀───────────────────┘
                          ▼
                   ┌─────────────────────────────┐
                   │ 階層的推奨値計算            │
                   │                             │
                   │ if (total >= 4096)          │
                   │   while loop (reserve計算)  │
                   │   recommendedMax = total -  │
                   │                  reserve*1024│
                   │ else                        │
                   │   recommendedMax = total*0.5│
                   │                             │
                   │ recommendedMax /= instCount │
                   └─────────────────────────────┘
                                │
                                ▼
                   PSCustomObject
                   (RecommendedValue含む)
                                │
                                ▼
                   Select-DefaultView ──────▶ パイプライン出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Test-DbaMaxMemory.ps1 | `public/Test-DbaMaxMemory.ps1` | ソース | メイン関数実装 |
| Get-DbaMaxMemory.ps1 | `public/Get-DbaMaxMemory.ps1` | ソース | 現在のメモリ設定取得 |
| Get-DbaService.ps1 | `public/Get-DbaService.ps1` | ソース | SQLサービス情報取得 |
| Connect-DbaInstance.ps1 | `public/Connect-DbaInstance.ps1` | ソース | SQL Server接続処理 |
| Set-DbaMaxMemory.ps1 | `public/Set-DbaMaxMemory.ps1` | ソース | 連携先（パイプライン） |
