# 画面設計書 264-重複インデックス検索

## 概要

本ドキュメントは、dbatoolsの重複インデックス検索機能に関する画面設計書です。ストレージスペースを浪費し、INSERT/UPDATE/DELETE操作のパフォーマンスを低下させる重複・重複インデックスを識別するためのPowerShellコマンドを定義します。

### 本画面の処理概要

本機能は、データベーステーブルをスキャンして同一または重複するカラム構造を持つインデックスを識別し、不要なストレージ消費と書き込みパフォーマンス低下の原因となるインデックスを検出するFind-DbaDbDuplicateIndexコマンドを提供します。

**業務上の目的・背景**：重複インデックスは完全に同一のキー列、インクルード列、フィルター条件を持ち、重複インデックスは一部のキー列を共有しながら異なる構造を持ちます。これらは不要なストレージを消費し、INSERT、UPDATE、DELETE操作を遅くします。本機能はインデックスメンテナンス時に冗長なインデックスを排除し、パフォーマンスに影響を与える前に対処することを支援します。

**画面へのアクセス方法**：PowerShellコンソールから以下のコマンドを実行してアクセスします。
```powershell
Find-DbaDbDuplicateIndex -SqlInstance <インスタンス名>
```

**主要な操作・処理内容**：
1. 指定されたSQL Serverインスタンスへの接続
2. 対象データベースの特定（全データベースまたは指定データベース）
3. sys.indexesとsys.index_columnsを使用した重複インデックス検索
4. キー列、インクルード列、ソート順（ASC/DESC）の比較
5. インデックスサイズ、行数、圧縮設定等の詳細情報取得
6. 重複インデックス（IncludeOverlapping指定時）の検索

**画面遷移**：
- `Connect-DbaInstance`で接続を確立後に実行可能
- パイプライン入力対応（SqlInstanceパラメータ）
- 取得結果は`Export-Csv`等で出力可能

**権限による表示制御**：
- データベースへの接続権限が必要
- sys.indexes、sys.index_columns、sys.columns、sys.dm_db_partition_stats等へのSELECT権限が必要

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 313 | Find-DbaDbDuplicateIndex | 主機能 | 重複インデックスの検索 |

## 画面種別

CLI（コマンドラインインターフェース）- PowerShellコマンド

## URL/ルーティング

PowerShellコマンド: `Find-DbaDbDuplicateIndex`

## 入出力項目

### パラメータ

| パラメータ名 | 型 | 必須 | 説明 |
|-------------|-----|------|------|
| SqlInstance | DbaInstanceParameter[] | Yes | 対象SQL Serverインスタンス（パイプライン入力対応） |
| SqlCredential | PSCredential | No | 代替認証情報 |
| Database | object[] | No | 対象データベース（ワイルドカード対応） |
| IncludeOverlapping | switch | No | 重複インデックス（部分一致）も検索 |
| EnableException | switch | No | 例外を有効化 |

## 表示項目

### 出力オブジェクト（PSCustomObject）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| DatabaseName | string | インデックスを含むデータベース名 |
| TableName | string | インデックスを含むテーブル名（schema.table形式） |
| IndexName | string | インデックス名 |
| KeyColumns | string | キー列のカンマ区切りリスト（ASC/DESC付き） |
| IncludedColumns | string | インクルード列のカンマ区切りリスト（ASC/DESC付き） |
| IndexType | string | インデックスタイプ（CLUSTERED, NONCLUSTERED） |
| IndexSizeMB | decimal | インデックスサイズ（MB） |
| RowCount | int | テーブルの行数 |
| IsDisabled | bool | インデックスが無効化されているか |
| IsUnique | bool | ユニークインデックスか |
| IsFiltered | bool | フィルタードインデックスか（SQL Server 2008以降） |
| CompressionDescription | string | データ圧縮タイプ（NONE, ROW, PAGE）（SQL Server 2008以降） |

## イベント仕様

### 1-Find-DbaDbDuplicateIndex実行

1. beginブロックでSQL Server 2005用と2008以降用のクエリを定義
2. SqlInstanceパラメータの各インスタンスに対してループ処理
3. Connect-DbaInstanceで接続（MinimumVersion 9 = SQL Server 2005以降）
4. Database指定時は対象データベースをフィルタリング
5. バージョンとIncludeOverlappingに応じたクエリを選択
6. db.Query()でクエリを実行し結果を出力

### 2-重複判定ロジック

**完全重複（デフォルト）**:
- 同一テーブル内でKeyColumnsとIncludedColumnsが完全一致
- SQL 2008以降はIsFilteredも比較対象

**重複（IncludeOverlapping指定時）**:
- 同一テーブル内でKeyColumnsが部分一致（前方一致）
- 例: (CustomerID)と(CustomerID, OrderDate)は重複

### 3-SQL Serverバージョン別クエリ

- **SQL Server 2005**: IsFiltered、CompressionDescriptionなし
- **SQL Server 2008以降**: IsFiltered（has_filter）、CompressionDescription（data_compression_desc）あり

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| Find-DbaDbDuplicateIndex | sys.indexes | SELECT | インデックス定義の取得 |
| Find-DbaDbDuplicateIndex | sys.index_columns | SELECT | インデックス列情報の取得 |
| Find-DbaDbDuplicateIndex | sys.columns | SELECT | 列定義の取得 |
| Find-DbaDbDuplicateIndex | sys.dm_db_partition_stats | SELECT | パーティション統計の取得 |
| Find-DbaDbDuplicateIndex | sys.partitions | SELECT | パーティション情報の取得 |

本コマンドは読み取り専用操作のみを行い、データベースの変更は行いません。

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 発生条件 |
|-------------|------|--------------|---------|
| MSG001 | エラー | Failure | 接続エラー |
| MSG002 | 情報 | Getting indexes from database '{db}'. | 詳細出力時 |
| MSG003 | エラー | Query failure | クエリ実行エラー |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| 接続エラー | Stop-FunctionでConnectionErrorカテゴリのエラーを報告し次のインスタンスへ |
| クエリ実行エラー | Stop-Functionでエラーを報告（-Target $db指定） |
| 最小バージョン未満 | Connect-DbaInstanceで-MinimumVersion 9を指定（SQL 2005以降） |

## 備考

- SQL Server 2005以降に対応（MinimumVersion 9）
- SQL Server 2005では、IsFilteredとCompressionDescriptionプロパティは含まれない
- CTEを使用してインデックス情報を集約
- IncludeOverlapping指定時はLIKE演算子で前方一致を検出
- 同一インデックス名との比較は除外（CI1.IndexName <> CI2.IndexName）
- システムスキーマ（sys）のオブジェクトは除外

---

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

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

### 推奨読解順序

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

本コマンドで使用される4種類のSQLクエリの構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Find-DbaDbDuplicateIndex.ps1 | `public/Find-DbaDbDuplicateIndex.ps1` | 行106-191のexactDuplicateQuery2005 |
| 1-2 | Find-DbaDbDuplicateIndex.ps1 | `public/Find-DbaDbDuplicateIndex.ps1` | 行193-286のoverlappingQuery2005 |
| 1-3 | Find-DbaDbDuplicateIndex.ps1 | `public/Find-DbaDbDuplicateIndex.ps1` | 行289-380のexactDuplicateQuery（2008以降） |
| 1-4 | Find-DbaDbDuplicateIndex.ps1 | `public/Find-DbaDbDuplicateIndex.ps1` | 行382-470のoverlappingQuery（2008以降） |

**読解のコツ**: CTE（CTE_IndexCols, CTE_IndexSpace）の構造と、WHERE句のEXISTS条件による重複判定ロジックを理解します。

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

processブロックでのクエリ選択と実行フローを理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Find-DbaDbDuplicateIndex.ps1 | `public/Find-DbaDbDuplicateIndex.ps1` | 行472-507のprocessブロック |

**主要処理フロー**:
1. **473行**: Test-FunctionInterruptでの中断チェック
2. **476-480行**: Connect-DbaInstanceで接続（MinimumVersion 9）
3. **482-486行**: データベースのフィルタリング
4. **492-498行**: バージョンとIncludeOverlappingに応じたクエリ選択
5. **500行**: db.Query($query)でクエリ実行

#### Step 3: 重複判定ロジックを理解する

EXISTS句での重複判定条件を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Find-DbaDbDuplicateIndex.ps1 | `public/Find-DbaDbDuplicateIndex.ps1` | 行183-191のexactDuplicate判定 |
| 3-2 | Find-DbaDbDuplicateIndex.ps1 | `public/Find-DbaDbDuplicateIndex.ps1` | 行270-286のoverlapping判定 |

**exactDuplicate判定**:
```sql
WHERE CI1.KeyColumns = CI2.KeyColumns
  AND CI1.IncludedColumns = CI2.IncludedColumns
  AND CI1.IndexName <> CI2.IndexName
```

**overlapping判定**:
```sql
WHERE (CI1.KeyColumns LIKE CI2.KeyColumns + '%' AND SUBSTRING(...) = ' ')
   OR (CI2.KeyColumns LIKE CI1.KeyColumns + '%' AND SUBSTRING(...) = ' ')
```

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

```
Find-DbaDbDuplicateIndex
    |
    +-- begin block
    |       +-- exactDuplicateQuery2005 定義
    |       +-- overlappingQuery2005 定義
    |       +-- exactDuplicateQuery 定義（2008以降）
    |       +-- overlappingQuery 定義（2008以降）
    |
    +-- process block
            |
            +-- foreach ($instance in $SqlInstance)
                    |
                    +-- Connect-DbaInstance (MinimumVersion=9)
                    |
                    +-- $server.Databases フィルタリング
                    |
                    +-- foreach ($db in $databases)
                            |
                            +-- バージョンチェック ($server.versionMajor)
                            |       +-- eq 9: SQL 2005用クエリ
                            |       +-- gt 9: SQL 2008以降用クエリ
                            |
                            +-- IncludeOverlappingチェック
                            |       +-- true: overlappingQuery
                            |       +-- false: exactDuplicateQuery
                            |
                            +-- $db.Query($query)
```

### データフロー図

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

SqlInstance          +------------------+
SqlCredential    -->| Connect-Dba      |
                     | Instance         |
                     +--------+---------+
                              |
                              v
Database             +------------------+
                 -->| Databases        |
                     | フィルタリング   |
                     +--------+---------+
                              |
                              v
IncludeOverlapping   +------------------+
server.versionMajor->| クエリ選択       |
                     | (4パターン)      |
                     +--------+---------+
                              |
                              v
                     +------------------+
                     | db.Query()       |---> PSCustomObject[]
                     +------------------+     (重複インデックス情報)
                              |
                              v
                     [CTE_IndexCols + CTE_IndexSpace]
                            +-- sys.indexes
                            +-- sys.index_columns
                            +-- sys.columns
                            +-- sys.dm_db_partition_stats
                            +-- sys.partitions
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Find-DbaDbDuplicateIndex.ps1 | `public/Find-DbaDbDuplicateIndex.ps1` | ソース | 重複インデックス検索の主要ロジック |
| Connect-DbaInstance.ps1 | `public/Connect-DbaInstance.ps1` | 依存 | SQL Server接続処理 |
