# 画面設計書 54-データベース縮小

## 概要

本ドキュメントは、dbatools PowerShellモジュールにおけるデータベース縮小（Database Shrink）機能の設計仕様を記載したものです。データベースファイル（データファイル、ログファイル）のサイズ縮小機能を提供します。

### 本画面の処理概要

本機能は、SQL Serverデータベースのファイルサイズを縮小するためのPowerShellコマンドを提供します。未使用領域を解放してディスクスペースを回収しますが、インデックスの断片化を引き起こす可能性があるため、慎重に使用する必要があります。

**業務上の目的・背景**：データベースの縮小は、大量データ削除後のディスク領域回収、データベース移行前のサイズ最適化、緊急のディスク容量不足対応など、特定のシナリオで必要となる操作です。ただし、縮小操作はインデックスの深刻な断片化（最大99%）を引き起こし、パフォーマンスに悪影響を与える可能性があるため、本番環境での実行は慎重に検討する必要があります。本機能は、チャンク分割による段階的な縮小や断片化統計の取得など、縮小操作のリスクを軽減する機能を提供します。

**画面へのアクセス方法**：PowerShellコンソールまたはスクリプトから以下のコマンドを実行してアクセスします:
- `Invoke-DbaDbShrink` - データベースの縮小実行

**主要な操作・処理内容**：
1. 対象データベース・ファイルの選択
2. 縮小前の空き領域およびインデックス断片化の確認
3. 指定された空き領域パーセントまでの縮小実行
4. チャンク分割による段階的縮小（オプション）
5. 縮小後のインデックス断片化統計の取得
6. 縮小結果のレポート出力

**画面遷移**：本機能はCLIコマンドであり、Get-DbaDatabase からパイプライン入力を受け取ることができます。縮小後は、インデックス再構築コマンド（Invoke-DbaDbIndexRebuild等）との連携が推奨されます。

**権限による表示制御**：データベース縮小には対象データベースへのdb_owner権限または同等の権限が必要です。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 170 | Invoke-DbaDbShrink | 主機能 | データベースの縮小実行 |

## 画面種別

実行（CLI）

## URL/ルーティング

PowerShellコマンドとして以下のコマンドレット名でアクセス:
- `Invoke-DbaDbShrink`

## 入出力項目

### Invoke-DbaDbShrink パラメータ

| パラメータ名 | 必須 | 型 | 説明 |
|-------------|------|-----|------|
| SqlInstance | No | DbaInstanceParameter[] | 対象SQL Serverインスタンス |
| SqlCredential | No | PSCredential | 認証用資格情報 |
| Database | No | object[] | 対象データベース（ワイルドカード対応） |
| ExcludeDatabase | No | object[] | 除外データベース |
| AllUserDatabases | No | switch | 全ユーザーデータベースを対象 |
| PercentFreeSpace | No | int | 残す空き領域パーセント（0-99、デフォルト0） |
| ShrinkMethod | No | string | 縮小方法（Default/EmptyFile/NoTruncate/TruncateOnly） |
| FileType | No | string | 対象ファイルタイプ（All/Data/Log） |
| StepSize | No | int64 | チャンクサイズ（例: 100MB, 1GB） |
| StatementTimeout | No | int | コマンドタイムアウト（分、デフォルト0=無制限） |
| ExcludeIndexStats | No | switch | インデックス統計取得をスキップ |
| ExcludeUpdateUsage | No | switch | DBCC UPDATEUSAGE をスキップ |
| InputObject | No | Database[] | パイプライン入力 |
| EnableException | No | switch | 例外を有効化 |

## 表示項目

### Invoke-DbaDbShrink 出力プロパティ

| プロパティ名 | 型 | 説明 |
|-------------|-----|------|
| ComputerName | string | SQLサーバーのコンピュータ名 |
| InstanceName | string | SQLサーバーインスタンス名 |
| SqlInstance | string | フルインスタンス名 |
| Database | string | データベース名 |
| File | string | ファイル論理名 |
| Start | DateTime | 縮小開始日時 |
| End | DateTime | 縮小終了日時 |
| Elapsed | string | 経過時間（HH:mm:ss形式） |
| Success | bool | 縮小成功フラグ |
| InitialSize | dbasize | 縮小前ファイルサイズ |
| InitialUsed | dbasize | 縮小前使用領域 |
| InitialAvailable | dbasize | 縮小前空き領域 |
| TargetAvailable | dbasize | 目標空き領域 |
| FinalAvailable | dbasize | 縮小後空き領域 |
| FinalSize | dbasize | 縮小後ファイルサイズ |
| InitialAverageFragmentation | decimal | 縮小前平均断片化率 |
| FinalAverageFragmentation | decimal | 縮小後平均断片化率 |
| InitialTopFragmentation | decimal | 縮小前最大断片化率 |
| FinalTopFragmentation | decimal | 縮小後最大断片化率 |
| Notes | string | 注意事項メッセージ |

## イベント仕様

### 1-データベース縮小実行

1. `Connect-DbaInstance`でSQL Serverインスタンスに接続
2. 対象データベースの選択（パラメータまたはパイプライン入力）
3. データベーススナップショットの除外（スナップショットは縮小不可）
4. 対象ファイル（データ/ログ/両方）の取得
5. 縮小前のファイルサイズと空き領域の計算
6. インデックス断片化統計の取得（ExcludeIndexStats未指定時）
7. DBCC UPDATEUSAGEの実行（ExcludeUpdateUsage未指定時）
8. 縮小の実行（StepSize指定時はチャンク分割）
9. 縮小後のファイルサイズと断片化統計の取得
10. 結果オブジェクトの出力

### 2-チャンク分割縮小

1. StepSizeパラメータで指定されたサイズでチャンク分割
2. 各イテレーションで段階的にファイルサイズを縮小
3. 各ステップ後にファイル情報をリフレッシュ
4. 目標サイズに達するか、これ以上縮小できない場合に終了

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| Invoke-DbaDbShrink | データファイル | DBCC SHRINKFILE | ファイルの物理サイズ縮小 |
| Invoke-DbaDbShrink | sys.dm_db_index_physical_stats | SELECT | 断片化統計の取得 |
| Invoke-DbaDbShrink | - | DBCC UPDATEUSAGE | 領域使用量情報の更新 |

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

本機能はデータベースファイルの物理サイズを変更する操作であり、ユーザーテーブルのデータは変更されません。ただし、データページの再配置によりインデックスの物理的な配置が変更されます。

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|---------|
| MSG-001 | エラー | StepSize is measured in bits. Did you mean $StepSize bits? | StepSizeが1024未満の場合 |
| MSG-002 | エラー | You must specify databases to execute against | Database/ExcludeDatabase/AllUserDatabases未指定時 |
| MSG-003 | 警告 | The database $db on server $instance is a snapshot and cannot be shrunk | スナップショットの場合 |
| MSG-004 | 警告 | File size of ($startingSizeKB) is less than or equal to the desired outcome | 縮小不要の場合 |
| MSG-005 | 情報 | Notes: Database shrinks can cause massive index fragmentation... | 常に出力 |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| 接続エラー | Stop-Functionで処理停止、エラーメッセージ出力 |
| データベーススナップショット | 警告メッセージを出力してスキップ |
| 縮小不要（既に目標サイズ以下） | 警告メッセージを出力してスキップ |
| 縮小失敗 | Successプロパティをfalseに設定、詳細エラーを出力 |
| タイムアウト | StatementTimeoutパラメータで制御 |

## 備考

- データベース縮小は最後の手段として使用すべき操作
- 縮小後は必ずインデックスの再構築または再編成を検討すること
- TruncateOnlyメソッドはデータ移動なしで末尾の空き領域のみ解放（最も低リスク）
- EmptyFileメソッドはファイル内の全データを他のファイルに移動
- 大規模データベースではStepSizeによるチャンク分割を推奨
- SQL Server 2000ではインデックス断片化統計は取得不可

---

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

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

### 推奨読解順序

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

縮小処理に関連するデータ構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SMO Database.FileGroups | Microsoft.SqlServer.Management.Smo | ファイルグループとファイルの構造 |
| 1-2 | SMO DataFile | Microsoft.SqlServer.Management.Smo | データファイルのSize, UsedSpaceプロパティ |
| 1-3 | sys.dm_db_index_physical_stats | システムDMV | 断片化統計の取得方法 |

**読解のコツ**: ファイルサイズはKB単位でSMOから取得され、dbasize型に変換されて出力されます。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Invoke-DbaDbShrink.ps1 | `public/Invoke-DbaDbShrink.ps1` | 縮小処理のメインロジック |

**主要処理フロー (Invoke-DbaDbShrink)**:
1. **行193-211**: begin ブロック - パラメータ検証とSQL準備
2. **行213-245**: データベースオブジェクトの取得とフィルタリング
3. **行253-264**: スナップショット確認とファイル取得
4. **行267-281**: 縮小前のサイズと目標サイズの計算
5. **行285-326**: 縮小実行（チャンク分割対応）
6. **行336-380**: 結果オブジェクトの構築と出力

#### Step 3: 断片化統計取得を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Invoke-DbaDbShrink.ps1 | `public/Invoke-DbaDbShrink.ps1` 行205-210 | 断片化統計取得SQL |

**断片化統計クエリ**:
```sql
SELECT
    AVG(avg_fragmentation_in_percent) AS [avg_fragmentation_in_percent],
    MAX(avg_fragmentation_in_percent) AS [max_fragmentation_in_percent]
FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL, NULL, NULL)
WHERE avg_fragmentation_in_percent > 0 AND page_count > 100
```

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

```
Invoke-DbaDbShrink
    |
    +-- パラメータ検証
    |       +-- StepSizeチェック
    |
    +-- Connect-DbaInstance
    |
    +-- データベース取得
    |       +-- Get-DbaDatabase (SqlInstance指定時)
    |       +-- パイプライン入力 (InputObject指定時)
    |
    +-- ファイル取得
    |       +-- $db.LogFiles
    |       +-- $db.FileGroups.Files
    |
    +-- 断片化統計取得（前）
    |       +-- sys.dm_db_index_physical_stats クエリ
    |
    +-- 縮小実行
    |       +-- $file.Shrink() (チャンク分割)
    |
    +-- 断片化統計取得（後）
    |       +-- sys.dm_db_index_physical_stats クエリ
    |
    +-- 結果出力
            +-- PSCustomObject
```

### データフロー図

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

SqlInstance/     ------>  Connect-DbaInstance
InputObject               |
                         v
Database/        ------>  データベース選択
ExcludeDatabase/          |
AllUserDatabases          v
                         スナップショット除外
                              |
FileType         ------>  ファイル取得
                         (LogFiles/FileGroups.Files)
                              |
                              v
                         縮小前統計取得
                         (Size, UsedSpace, Fragmentation)
                              |
PercentFreeSpace ------>  目標サイズ計算
                              |
                              v
ShrinkMethod     ------>  $file.Shrink() 実行
StepSize         ------>  (チャンク分割)
                              |
                              v
                         縮小後統計取得
                              |
                              v
                         PSCustomObject  ----->  出力
                         (InitialSize, FinalSize,
                          Fragmentation, Notes)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Invoke-DbaDbShrink.ps1 | `public/Invoke-DbaDbShrink.ps1` | ソース | データベース縮小コマンド |
| Get-DbaDatabase.ps1 | `public/Get-DbaDatabase.ps1` | ソース | データベースオブジェクト取得 |
| Connect-DbaInstance.ps1 | `public/Connect-DbaInstance.ps1` | ソース | インスタンス接続 |
