# 機能設計書 643-Invoke-DbaBalanceDataFiles

## 概要

本ドキュメントは、データベースのデータファイル間でデータを再バランスするdbatools PowerShellコマンド「Invoke-DbaBalanceDataFiles」の機能設計書です。

### 本機能の処理概要

Invoke-DbaBalanceDataFilesは、複数のデータファイルを持つデータベースにおいて、クラスタ化インデックスの再構築を通じてデータファイル間のデータ分散を均等化するコマンドです。

**業務上の目的・背景**：SQL Serverで大規模データベースに新しいデータファイルを追加した場合、SQL Serverは新しいファイルが既存ファイルと同程度のサイズになるまで、新しいファイルのみを使用します。これにより、I/Oの偏りやパフォーマンス低下が発生する可能性があります。本機能により、データファイル間でデータを均等に再分散し、I/O負荷を分散できます。

**機能の利用シーン**：
- 新しいデータファイル追加後のデータ再分散
- ストレージ移行後のデータバランス調整
- I/Oパフォーマンス最適化
- ディスク使用量の均等化
- ストレージ容量計画に基づくファイル再配置

**主要な処理内容**：
1. SQL Serverエディションと版のチェック（オンライン再構築サポート確認）
2. ディスク空き容量の検証（Windows環境）
3. データファイルの現状取得
4. バランス可能なテーブル（複数ファイルのファイルグループ内）の特定
5. クラスタ化インデックスの再構築（オンラインまたはオフライン）
6. データファイルの結果状態取得と出力

**関連システム・外部連携**：
- SQL Serverインスタンス（SMO）
- ファイルシステム（ディスク容量確認）

**権限による制御**：対象データベースに対するALTER INDEX権限、データベースファイルの変更権限が必要です。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | CLI専用 | 主機能 | コマンドライン実行のみ |

## 機能種別

データ最適化 / インデックス再構築

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| SqlInstance | DbaInstanceParameter[] | Yes | 対象SQL Serverインスタンス | - |
| SqlCredential | PSCredential | No | SQL Server接続用資格情報 | 有効なPSCredential |
| Database | object[] | Yes | 対象データベース名 | インスタンスに存在すること |
| Table | object[] | No | 対象テーブル名 | データベースに存在すること |
| RebuildOffline | switch | No | オフライン再構築を強制 | - |
| EnableException | switch | No | エラー時に例外をスロー | - |
| Force | switch | No | ディスク容量チェックをスキップ | - |

### 入力データソース

- 直接パラメータ指定

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ComputerName | string | SQL Serverインスタンスのコンピュータ名 |
| InstanceName | string | SQL Serverインスタンス名 |
| SqlInstance | string | 完全なインスタンス名 |
| Database | string | 対象データベース名 |
| Start | DateTime | バランス処理開始日時 |
| End | DateTime | バランス処理終了日時 |
| Elapsed | string | 経過時間（HH:mm:ss形式） |
| Success | bool | バランス処理成功フラグ |
| Unsuccessful | string | バランス失敗したテーブル名（カンマ区切り） |
| DataFilesStart | object[] | 処理前のデータファイル情報配列 |
| DataFilesEnd | object[] | 処理後のデータファイル情報配列 |

### 出力先

パイプライン出力（PSCustomObject）

## 処理フロー

### 処理シーケンス

```
1. SQL Serverへの接続
   └─ Connect-DbaInstanceで接続確立

2. データベース検証
   └─ 指定データベースの存在確認

3. エディション/バージョンチェック
   ├─ オンライン再構築サポート判定
   │   └─ SQL Server 2005以上かつEnterprise/Developer Edition
   └─ RebuildOffline指定時はオフラインモード強制

4. ディスク容量検証（Windows環境、Force未指定時）
   ├─ データベースファイルのディスク使用量取得
   └─ 空き容量との比較

5. データファイル現状取得（処理前）
   └─ Get-DbaDbFileでROWSファイルを取得

6. テーブル処理
   ├─ ファイルグループの検証（2ファイル以上、書き込み可能）
   ├─ バランス可能テーブルの特定
   └─ 各テーブルのクラスタ化インデックス再構築
       ├─ オンライン再構築（Enterprise/Developer）
       └─ オフライン再構築（その他）

7. データファイル現状取得（処理後）
   └─ Get-DbaDbFileでROWSファイルを取得

8. 結果オブジェクト出力
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[Connect-DbaInstance]
    B --> C{Database存在?}
    C -->|No| D[エラー終了]
    C -->|Yes| E{オンライン再構築サポート?}
    E -->|Yes| F[オンラインモード設定]
    E -->|No| G{RebuildOffline?}
    G -->|Yes| H[オフラインモード設定]
    G -->|No| I[ユーザー確認]
    I -->|Yes| H
    I -->|No| D
    F --> J{Force or 非Windows?}
    H --> J
    J -->|Yes| K[スキップ]
    J -->|No| L[ディスク容量チェック]
    L --> M{十分な空き?}
    M -->|No| D
    M -->|Yes| K
    K --> N[データファイル状態取得-開始]
    N --> O[テーブルループ]
    O --> P{バランス可能?}
    P -->|No| Q[unsuccessfulに追加]
    P -->|Yes| R[クラスタ化インデックス再構築]
    R --> S{成功?}
    S -->|No| Q
    S -->|Yes| T[次テーブル]
    Q --> T
    T --> O
    O --> U[データファイル状態取得-終了]
    U --> V[結果オブジェクト出力]
    V --> W[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | オンライン再構築条件 | SQL Server 2005以上かつEnterprise/Developer Editionでオンライン再構築可能 | 常時 |
| BR-002 | ファイルグループ条件 | 2つ以上のファイルを持ち、ReadOnlyでないファイルグループのテーブルのみ対象 | 常時 |
| BR-003 | クラスタ化インデックス必須 | ヒープテーブル（クラスタ化インデックスなし）は対象外 | 常時 |
| BR-004 | 単一ファイルDB除外 | データファイルが1つのみのデータベースは処理不可 | 常時 |
| BR-005 | ディスク容量検証 | DBファイルサイズ合計がディスク空き容量を超える場合はエラー | Windows環境、Force未指定時 |

### 計算ロジック

- Elapsed = New-TimeSpan -Start $start -End $end（HH:mm:ss形式）
- オンライン再構築可否 = (serverVersion >= 9) AND (Edition -like "Enterprise*" OR "Developer*")

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| インデックス再構築 | ユーザーテーブル | ALTER INDEX REBUILD | クラスタ化インデックスの再構築 |

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

#### ユーザーテーブル（クラスタ化インデックス）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| ALTER INDEX REBUILD | クラスタ化インデックス | ONLINE = ON/OFF | ファイルグループ内でデータ再分散 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ConnectionError | SQL Server接続失敗 | 接続情報を確認 |
| - | ValidationError | 指定データベースが存在しない | データベース名を確認 |
| - | ValidationError | 単一データファイルDB | データファイルを追加してから実行 |
| - | DiskSpaceError | ディスク空き容量不足 | 空き容量確保または-Force使用 |
| - | IndexRebuildError | インデックス再構築失敗 | エラーメッセージを確認 |

### リトライ仕様

リトライなし（テーブル単位でContinueしてスキップ）

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

各インデックス再構築は独立したトランザクションとして実行（SQL Server内部）

## パフォーマンス要件

- テーブルサイズとインデックス数に依存
- オンライン再構築: テーブルアクセス可能だが処理時間は長くなる
- オフライン再構築: テーブルロックだが処理時間は短い

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

- 対象データベースに対するALTER INDEX権限が必要
- オンライン再構築にはEnterprise/Developer Editionが必要
- 非Windows環境ではディスク容量チェックが行われない点に注意

## 備考

- ヒープテーブルは現時点で未サポート
- ShouldProcess対応（WhatIf/Confirm）
- ConfirmImpact = "Medium"

---

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

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

### 推奨読解順序

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

出力オブジェクトとDataFilesStart/DataFilesEndの構造を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Invoke-DbaBalanceDataFiles.ps1 | `public/Invoke-DbaBalanceDataFiles.ps1` | L375-387の出力オブジェクト定義 |

**読解のコツ**: DataFilesStart/DataFilesEndはGet-DbaDbFileの結果をフィルタリングしたもので、ID, LogicalName, PhysicalName, Size, UsedSpace, AvailableSpaceを含みます。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Invoke-DbaBalanceDataFiles.ps1 | `public/Invoke-DbaBalanceDataFiles.ps1` | processブロック全体の流れ |

**主要処理フロー**:
1. **124-126行目**: Forceパラメータ処理
2. **134-140行目**: Connect-DbaInstanceで接続
3. **142-151行目**: データベース検証
4. **153-183行目**: エディション/バージョンチェックとオンライン再構築判定
5. **186-224行目**: ディスク容量検証（Windows環境）
6. **227-244行目**: データファイル数チェック
7. **259-360行目**: テーブル処理ループとインデックス再構築

#### Step 3: オンライン再構築判定ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Invoke-DbaBalanceDataFiles.ps1 | `public/Invoke-DbaBalanceDataFiles.ps1` | L153-183のエディション判定 |

**主要処理フロー**:
- **157-158行目**: RebuildOffline指定時はオフラインモード
- **159-180行目**: エディション判定とユーザー確認ダイアログ
- **181-183行目**: Enterprise/Developer判定でオンラインモード設定

#### Step 4: インデックス再構築処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Invoke-DbaBalanceDataFiles.ps1 | `public/Invoke-DbaBalanceDataFiles.ps1` | L306-345のインデックス再構築 |

**主要処理フロー**:
- **309行目**: クラスタ化インデックスのループ
- **314行目**: 元のOnlineIndexOperation設定を保存
- **317-322行目**: RebuildOffline/オンライン設定の切り替え
- **325-339行目**: Rebuild()呼び出しとエラー処理
- **343行目**: 元の設定に復元

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

```
Invoke-DbaBalanceDataFiles
    │
    ├─ Connect-DbaInstance
    │
    ├─ Get-DbaDbFile（処理前データファイル取得）
    │
    ├─ Server.Query（ディスク使用量/空き容量取得）
    │      ├─ sys.master_files クエリ
    │      └─ xp_fixeddrives
    │
    ├─ FileGroups.EnumObjects()（バランス可能テーブル取得）
    │
    ├─ Indexes.Rebuild()（クラスタ化インデックス再構築）
    │      └─ SMO Index.Rebuild メソッド
    │
    └─ Get-DbaDbFile（処理後データファイル取得）
```

### データフロー図

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

SqlInstance ──────────┐
                      │
Database ─────────────┼──▶ Connect-DbaInstance ────────┐
                      │                                 │
Table ────────────────┤                                 ▼
                      │      ┌─────────────────────────────────┐
RebuildOffline ───────┤      │ エディション/ディスク容量検証     │
                      │      └─────────────────────────────────┘
Force ────────────────┘                  │
                                         ▼
                      ┌─────────────────────────────────────────┐
                      │ クラスタ化インデックス再構築             │
                      │ (オンライン or オフライン)              │
                      └─────────────────────────────────────────┘
                                         │
                                         ▼
                                  PSCustomObject
                                  (ComputerName,
                                   Database,
                                   DataFilesStart,
                                   DataFilesEnd,
                                   Success, etc.)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Invoke-DbaBalanceDataFiles.ps1 | `public/Invoke-DbaBalanceDataFiles.ps1` | ソース | メインコマンド実装 |
| Get-DbaDbFile.ps1 | `public/Get-DbaDbFile.ps1` | ソース | データファイル情報取得 |
| Connect-DbaInstance.ps1 | `public/Connect-DbaInstance.ps1` | ソース | SQL Server接続 |
| Invoke-DbaBalanceDataFiles.Tests.ps1 | `tests/Invoke-DbaBalanceDataFiles.Tests.ps1` | テスト | パラメータ検証テスト |
