# 機能設計書 4-sp_BlitzIndex

## 概要

本ドキュメントは、SQL Server First Responder Kitのsp_BlitzIndexストアドプロシージャの機能設計について記載する。sp_BlitzIndexはインデックスの設計とパフォーマンスを分析し、最適化提案を出力する診断ツールである。

### 本機能の処理概要

sp_BlitzIndexは、SQL Serverのインデックス構造、使用状況、欠落インデックスを包括的に分析し、インデックス設計の改善提案を出力するストアドプロシージャである。

**業務上の目的・背景**：インデックスはデータベースパフォーマンスの要であり、適切なインデックス設計はクエリ性能を大幅に向上させる。一方、過剰なインデックスは書き込み性能の低下やストレージの無駄遣いを招く。sp_BlitzIndexは、インデックスの使用状況を分析し、追加すべきインデックス、削除を検討すべきインデックスを自動的に特定する。

**機能の利用シーン**：
- インデックス設計のレビュー
- パフォーマンスチューニング時のインデックス分析
- 不要インデックスの特定と削除検討
- 欠落インデックスの提案確認
- インデックスメンテナンス計画の策定

**主要な処理内容**：
1. インデックス使用統計の収集（sys.dm_db_index_usage_stats）
2. インデックスサイズ・構造の分析
3. 欠落インデックス情報の取得（sys.dm_db_missing_index_*）
4. 問題パターンの検出（重複、未使用、ワイドキー等）
5. インデックス作成スクリプトの生成

**関連システム・外部連携**：
- sys.indexes: インデックスメタデータ
- sys.dm_db_index_usage_stats: 使用統計
- sys.dm_db_missing_index_*: 欠落インデックス情報
- sys.dm_db_index_operational_stats: 操作統計

**権限による制御**：
- VIEW DATABASE STATE権限が必要（対象データベースごと）
- VIEW SERVER STATE権限（サーバー全体分析時）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 6 | sp_BlitzIndex 診断結果画面 | 主機能 | @Mode=0でインデックスの問題を優先度付きで診断・表示 |
| 7 | sp_BlitzIndex サマリー画面 | 主機能 | @Mode=1でデータベースごとのインデックス数・使用スペース等のサマリーを表示 |
| 8 | sp_BlitzIndex 使用詳細画面 | 主機能 | @Mode=2で既存インデックスの使用統計詳細を一覧表示 |
| 9 | sp_BlitzIndex 欠落インデックス画面 | 主機能 | @Mode=3でSQL Serverが提案する欠落インデックスの一覧を表示 |

## 機能種別

データ分析 / インデックス診断 / 最適化提案

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| @ObjectName | NVARCHAR(386) | No | 対象オブジェクト名（db.schema.table形式） | NULL許可 |
| @DatabaseName | NVARCHAR(128) | No | 対象データベース名 | NULL時は現在のDB |
| @SchemaName | NVARCHAR(128) | No | 対象スキーマ名 | NULL許可 |
| @TableName | NVARCHAR(261) | No | 対象テーブル名 | NULL許可 |
| @Mode | TINYINT | No | 動作モード（0-4） | デフォルト0 |
| @Filter | TINYINT | No | フィルタモード（0-2） | デフォルト0 |
| @SkipPartitions | BIT | No | パーティション情報スキップ | デフォルト0 |
| @SkipStatistics | BIT | No | 統計情報スキップ | デフォルト1 |
| @GetAllDatabases | BIT | No | 全データベース分析 | デフォルト0 |
| @ShowColumnstoreOnly | BIT | No | カラムストアのみ表示 | デフォルト0 |
| @BringThePain | BIT | No | 大量データ許可 | デフォルト0 |
| @IgnoreDatabases | NVARCHAR(MAX) | No | 除外データベースリスト | NULL許可 |
| @ThresholdMB | INT | No | サイズ閾値(MB) | デフォルト250 |
| @OutputType | VARCHAR(20) | No | 出力形式 | デフォルトTABLE |
| @OutputServerName | NVARCHAR(256) | No | 出力先サーバー | NULL許可 |
| @OutputDatabaseName | NVARCHAR(256) | No | 出力先データベース | NULL許可 |
| @OutputSchemaName | NVARCHAR(256) | No | 出力先スキーマ | NULL許可 |
| @OutputTableName | NVARCHAR(261) | No | 出力先テーブル | NULL許可 |
| @IncludeInactiveIndexes | BIT | No | 非アクティブインデックス含む | デフォルト0 |
| @ShowAllMissingIndexRequests | BIT | No | 全欠落インデックス表示 | デフォルト0 |
| @SortOrder | NVARCHAR(50) | No | ソート順序（@Mode=2用） | NULL許可 |
| @SortDirection | NVARCHAR(4) | No | ソート方向 | デフォルトDESC |
| @Help | TINYINT | No | ヘルプ表示 | デフォルト0 |
| @Debug | BIT | No | デバッグモード | デフォルト0 |
| @Version | VARCHAR(30) | No | バージョン（OUTPUT） | 出力専用 |
| @VersionDate | DATETIME | No | バージョン日付（OUTPUT） | 出力専用 |

### 入力データソース

- sys.indexes: インデックス定義
- sys.index_columns: インデックス列情報
- sys.dm_db_index_usage_stats: 使用統計
- sys.dm_db_missing_index_details: 欠落インデックス詳細
- sys.dm_db_missing_index_groups: 欠落インデックスグループ
- sys.dm_db_index_operational_stats: 操作統計
- sys.dm_db_partition_stats: パーティション統計

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Priority | INT | 問題の優先度 |
| findings_group | NVARCHAR(4000) | 問題カテゴリ |
| finding | NVARCHAR(200) | 問題の名称 |
| database_name | NVARCHAR(128) | データベース名 |
| URL | NVARCHAR(200) | 詳細情報リンク |
| details | NVARCHAR(MAX) | 問題の詳細 |
| index_definition | NVARCHAR(MAX) | インデックス定義 |
| secret_columns | NVARCHAR(MAX) | 隠れ列（クラスタ化キー等） |
| index_usage_summary | NVARCHAR(MAX) | 使用状況サマリー |
| index_size_summary | NVARCHAR(MAX) | サイズサマリー |
| create_tsql | NVARCHAR(MAX) | 作成用T-SQL |
| more_info | NVARCHAR(MAX) | 追加情報取得コマンド |

### 出力先

- 画面表示（デフォルト）
- 指定テーブルへの出力（@OutputTableName指定時）

## 処理フロー

### 処理シーケンス

```
1. パラメータ検証と初期化
   └─ @Mode、対象データベースの設定

2. 対象データベースの特定
   └─ @GetAllDatabases=1時は全DB、それ以外は指定DB

3. インデックスメタデータ収集
   └─ sys.indexes、sys.index_columnsからの情報取得

4. 使用統計の収集
   └─ dm_db_index_usage_statsからの情報取得

5. モード別分析実行
   └─ @Modeに応じた分析処理

6. 結果出力
   └─ 優先度順に結果セット返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{@Help = 1?}
    B -->|Yes| C[ヘルプ出力]
    C --> Z[終了]
    B -->|No| D[パラメータ初期化]
    D --> E{@Mode値?}
    E -->|0| F[診断モード]
    E -->|1| G[サマリーモード]
    E -->|2| H[使用詳細モード]
    E -->|3| I[欠落インデックスモード]
    E -->|4| J[詳細診断モード]
    F --> K[インデックス情報収集]
    G --> K
    H --> K
    I --> K
    J --> K
    K --> L[使用統計収集]
    L --> M[問題検出]
    M --> N[結果出力]
    N --> Z
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | Mode指定 | @Mode=0:診断、1:サマリー、2:使用詳細、3:欠落詳細、4:詳細診断 | 常時 |
| BR-002 | サイズ閾値 | @ThresholdMB以上のオブジェクトのみ基本結果に含める | @Mode=0時 |
| BR-003 | Filter適用 | @Filter=1:読取0の低使用警告なし、@Filter=2:500MB以上のみ | @Mode=0時 |
| BR-004 | 全DB分析 | @GetAllDatabases=1で全データベース分析 | 複数DB分析時 |
| BR-005 | 除外DB | @IgnoreDatabasesで指定DBを除外 | @GetAllDatabases=1時 |

### 計算ロジック

**インデックス使用率計算**:
```sql
reads_per_write = (user_seeks + user_scans + user_lookups) / NULLIF(user_updates, 0)
total_reads = user_seeks + user_scans + user_lookups
```

**インデックスサイズ計算**:
```sql
total_pages = reserved_page_count
size_mb = (total_pages * 8) / 1024.0
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 参照 | sys.indexes | SELECT | インデックス定義取得 |
| 参照 | sys.index_columns | SELECT | インデックス列取得 |
| 参照 | sys.dm_db_index_usage_stats | SELECT | 使用統計取得 |
| 参照 | sys.dm_db_missing_index_* | SELECT | 欠落インデックス取得 |
| 参照 | sys.dm_db_partition_stats | SELECT | サイズ情報取得 |
| 挿入 | 出力テーブル | INSERT | 結果出力（オプション） |

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

#### #IndexSanity（一時テーブル）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | index_sanity_id, database_id, object_id等 | インデックス情報収集 | メイン情報格納 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 無効OutputType | TABLE/NONE以外 | RAISERRORでエラー通知 |
| - | 無効統計サンプリング率 | 0未満または100超 | RAISERRORでエラー通知 |
| - | 出力パラメータ不足 | @OutputType='NONE'で出力先未指定 | RAISERRORでエラー通知 |

### リトライ仕様

特定のリトライ機能は実装されていない。

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

READ UNCOMMITTED分離レベルで実行される。

## パフォーマンス要件

- 通常実行: 数秒から数十秒（データベースサイズに依存）
- @GetAllDatabases=1: データベース数とインデックス数に比例して増加

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

- VIEW DATABASE STATE権限が必要（対象データベース）
- VIEW SERVER STATE権限（@GetAllDatabases=1時）

## 備考

- バージョン: 8.29（2026年2月3日時点）
- インデックス作成スクリプトはONLINE=?形式（ユーザー判断が必要）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sp_BlitzIndex.sql | `sp_BlitzIndex.sql` | **366-384行目**: #BlitzIndexResults一時テーブル定義 |
| 1-2 | sp_BlitzIndex.sql | `sp_BlitzIndex.sql` | **386-500行目**: #IndexSanity一時テーブル定義 |

**読解のコツ**: #IndexSanityがインデックスメタデータの主要格納先。計算列（index_definition, index_usage_summary等）の定義に注目。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | sp_BlitzIndex.sql | `sp_BlitzIndex.sql` | **15-47行目**: ALTER PROCEDURE定義とパラメータ |
| 2-2 | sp_BlitzIndex.sql | `sp_BlitzIndex.sql` | **49-59行目**: 初期設定とバージョンチェック |

**主要処理フロー**:
1. **49-51行目**: SET NOCOUNT ON、STATISTICS XML OFF、READ UNCOMMITTED設定
2. **53行目**: バージョン情報設定
3. **139-162行目**: @ObjectNameからの@DatabaseName/@SchemaName/@TableName抽出

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

```
sp_BlitzIndex
    │
    ├─ sys.indexes (インデックス定義)
    │
    ├─ sys.index_columns (インデックス列)
    │
    ├─ sys.dm_db_index_usage_stats (使用統計)
    │
    ├─ sys.dm_db_missing_index_* (欠落インデックス)
    │
    ├─ sys.dm_db_partition_stats (サイズ情報)
    │
    └─ #IndexSanity, #BlitzIndexResults (一時テーブル)
```

### データフロー図

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

パラメータ ──────────────────▶ パラメータ検証 ─────────────────▶ #IndexSanity
   │                              │                                   │
sys.indexes ─────────────────▶ インデックス情報収集 ─────────────▶ │
   │                              │                                   │
sys.index_columns ───────────▶ 列情報収集 ───────────────────────▶ │
   │                              │                                   │
dm_db_index_usage_stats ─────▶ 使用統計収集 ─────────────────────▶ │
   │                              │                                   │
dm_db_missing_index_* ───────▶ 欠落インデックス収集 ─────────────▶ │
                                  │                                   │
                            問題検出・分析 ◀──────────────────────────┘
                                  │
                                  ▼
                         [結果セット/テーブル]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| sp_BlitzIndex.sql | `sp_BlitzIndex.sql` | ソース | メインストアドプロシージャ定義 |
