データベース: 統計情報の更新方法（手動更新と自動更新）

# データベース: 統計情報の更新方法

## 目次
1. [統計情報とは](#統計情報とは)
2. [更新のタイミングとトリガー](#更新のタイミングとトリガー)
3. [手動 vs 自動の決定](#手動-vs-自動の決定)
4. [更新頻度の最適化](#更新頻度の最適化)
5. [更新失敗時のトラブルシューティング](#更新失敗時のトラブルシューティング)
6. [各製品のメンテナンスツール（コマンド）](#各製品のメンテナンスツール)
7. [まとめ](#まとめ)

## 統計情報とは

統計情報は、データベースに格納されているデータの分布や特性を把握し、クエリの実行計画を最適化するために利用される重要なメタデータです。データベース管理システム（DBMS）は、この統計情報を基に、最適なクエリプランを選定し、パフォーマンスを向上させます。

### 統計情報に含まれる主な項目
- **ヒストグラム**: 特定のカラム内の値の分布や頻度を示すデータ。クエリのフィルタ条件に基づくパフォーマンス最適化に役立ちます。
- **NULLの数**: NULL値が含まれているデータの割合を記録し、クエリの最適化に使用されます。
- **最大値と最小値**: 特定カラムのデータの範囲を示し、範囲検索などのクエリパフォーマンスに影響します。
- **重複データの頻度**: 特定のカラムにおける重複値の割合を示し、インデックスの使用効率に影響を与える重要な要素です。

### 統計情報の重要性
統計情報が最新の状態で維持されていれば、DBMSは効率的なクエリ実行計画を選択することができます。しかし、統計情報が古くなると、非効率なプランが選択され、パフォーマンスが低下するリスクが高まります。

### 具体例
例えば、インデックスを使用した検索が必要な場合、統計情報に基づいてクエリプランが決定されます。カラムに多くの重複値がある場合、インデックススキャンではなくシーケンシャルスキャンが選択されることもあります。統計情報が適切に更新されていないと、不適切な実行計画が選ばれ、クエリの処理速度が遅くなります。


## 更新のタイミングとトリガー

### 更新のタイミング
- **定期的な更新**: 夜間バッチ処理後やメンテナンスウィンドウ中に実施するのが一般的。
- **大量データの変更後**: 大きなデータ変更（10%以上）が発生した場合は統計情報の更新が推奨される。
- **オンデマンド更新**: パフォーマンス問題が発生した際には即座に手動で更新を行う。

### トリガー
- **データ変更割合**: Oracleの場合、テーブルの10%以上が変更されたとき、自動的に統計情報が古くなるとみなされ、更新がトリガーされる。
- **イベント発生後**: バッチ処理やデータ移行後など、特定のイベントが発生した際に統計情報の更新が必要になる。
- **パフォーマンス低下時**: クエリのパフォーマンスが低下した場合、手動で統計情報を更新する必要がある。


## 手動 vs 自動の決定

### 自動更新
- **メリット**:
  - 定期的に自動で統計情報を更新できるため、管理の手間が少ない。
  - データベース全体のパフォーマンスを維持でき、定期的なメンテナンスが不要。
  
- **デメリット**:
  - 必ずしも最適なタイミングで更新されるわけではなく、バッチ処理やリソースが逼迫している時間帯に実行されることで、パフォーマンスが悪化する可能性がある。
  - 特定のテーブルに対する細かい対応が難しい。

### 手動更新
- **メリット**:
  - 柔軟なタイミングで更新でき、特定のテーブルやクエリに対して優先的に対応できる。
  - バッチ処理後やシステムリソースが余裕のある時間帯を選んで実行可能で、業務に与える影響を最小限にできる。
  
- **デメリット**:
  - 手動で定期的に更新する必要があるため、管理コストが高くなる。
  - 手動更新を怠ると統計情報が古くなり、パフォーマンスの低下を招くリスクがある。

### 手動と自動の併用
- **戦略**: 一般的な運用では自動更新を実施し、重要なバッチ処理や業務に応じて手動更新を行うことで、柔軟かつ効率的な運用が可能となる。

![スクリーンショット 2024-09-17 22.23.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3880450/bb0fe32a-195d-6b62-1827-7121150cc8ea.png)



### 各RDSの自動更新の有無と発動条件
- **Amazon RDS for Oracle**: 自動更新あり。デフォルトで10%以上のデータ変更があった場合、夜間に自動更新。
- **Amazon RDS for PostgreSQL**: 自動更新あり。テーブルの20%以上が変更されたときに自動更新。
- **Amazon RDS for MySQL/MariaDB**: 自動更新あり。テーブル操作時に自動で統計情報を更新。
- **Amazon RDS for SQL Server**: 自動更新あり。20% + 500行以上のデータが変更された場合に自動更新。
- **Azure SQL Database**: 自動更新あり。SQL Serverと同様に、20% + 500行以上のデータ変更で自動更新。
- **PostgreSQL**: 自動更新あり。テーブルの20%以上の行が変更された場合に自動更新。


## 更新頻度の最適化

### 更新頻度の重要性
統計情報の更新は、データベースパフォーマンスを最適に保つための重要な要素です。更新頻度が適切でない場合、パフォーマンスが低下し、リソースを無駄に消費する可能性があります。

### 頻繁なデータ更新の場合
- データ変更が頻繁に行われるシステムでは、統計情報を定期的に更新することが重要です。
- 特に、リアルタイムでデータが増減するeコマースやSNSのようなシステムでは、統計情報の更新頻度を高く保つことで、クエリパフォーマンスを維持します。

### データ変更が少ない場合
- 更新頻度を下げ、リソースを効率的に利用できます。
- バッチ処理後など、必要なタイミングでのみ統計情報を更新し、無駄なリソース消費を防ぎます。

### リソース負荷を考慮した最適化
- 統計情報の更新はCPU、メモリ、I/Oリソースを消費します。システムに大きな負荷をかけないように、リソースが余裕のある時間帯やバッチ処理後に更新を行うのが理想的です。

### パフォーマンスモニタリングと調整
- モニタリングツールを活用し、統計情報の更新が必要なタイミングを適切に把握し、リソースの消費やパフォーマンスに基づいて更新頻度を調整します。



## 更新失敗時のトラブルシューティング

### エラーログの確認
- 更新が失敗した場合、まずはエラーログを確認して問題の原因を特定します。`DBMS_SCHEDULER`などを使用して自動化されたタスクのログも確認できます。
- **手順**: `DBA_SCHEDULER_JOB_LOG` や `DBA_SCHEDULER_JOB_RUN_DETAILS` ビューでエラーを調査し、特定のエラーメッセージや番号を確認。

### リソース不足の確認
- 統計情報の更新にはリソース（CPU、メモリ、I/O）が必要です。リソース不足の状態では更新が失敗する可能性があります。
- **対策**: CPUやメモリの使用率、I/Oの負荷状況をモニタリングし、リソースを追加したり、リソース負荷の少ない時間帯に再実行を行います。

### テーブルのロック確認
- 更新中に別のプロセスがテーブルをロックしていると、統計情報の更新が失敗することがあります。
- **対策**: `v$lock` ビューでテーブルのロック状況を確認し、必要に応じてロックを解除します。

### ディスクスペースの確認
- 統計情報の更新にはディスクスペースが必要です。スペース不足によって更新が失敗することがあります。
- **対策**: ディスクの空き容量を確認し、不足している場合は不要なファイルを削除するか、ディスク容量を拡張します。

### パラメータ設定の見直し
- `autovacuum` や `ANALYZE` のパラメータ設定が不適切だと、統計情報の更新が正しく行われないことがあります。
- **対策**: `autovacuum` 設定や `work_mem` の値を確認し、リソースに応じて適切に調整します。

### 手動での再実行
- 自動更新が失敗した場合、手動で統計情報を更新することが必要です。`DBMS_STATS.GATHER_TABLE_STATS` などを使って手動で実行します。
- **コマンド例**:
  ```sql
  BEGIN
    DBMS_STATS.GATHER_TABLE_STATS('schema_name', 'table_name');
  END;
  ```
### エラーログの通知設定
- 更新失敗時にすぐ対応できるよう、エラーが発生した際にはメール通知などを設定しておくことが有効です。これにより、問題が発生しても迅速に対応できます。
- **対策**: Oracleの場合、`DBMS_SCHEDULER` で通知設定を行い、失敗時にアラートを受け取るようにします。


## 各製品のメンテナンスツール

Amazon RDS の各種データベースで使用できる、統計情報の更新に使用される主要なメンテナンスツールやコマンドを紹介します。

### Amazon RDS for PostgreSQL
- **コマンド**: `ANALYZE`
  - PostgreSQLで統計情報を更新するためのコマンドです。自動的に統計情報を収集しますが、手動での更新も可能です。
  - **コマンド例**:
    ```sql
    ANALYZE; -- 全テーブルの統計情報を更新
    ANALYZE my_table; -- 特定のテーブルの統計情報を更新
    ```

### Amazon RDS for MySQL / MariaDB
- **コマンド**: `ANALYZE TABLE`
  - MySQLおよびMariaDBでは、`ANALYZE TABLE` を使用して統計情報を更新します。インデックス統計情報も再計算され、クエリプランの精度が向上します。
  - **コマンド例**:
    ```sql
    ANALYZE TABLE my_table; -- 特定テーブルの統計情報を更新
    ```

### Amazon RDS for Oracle
- **コマンド**: `DBMS_STATS`
  - Oracleでは、`DBMS_STATS` パッケージを使って統計情報を収集・更新します。自動的に統計情報が更新されますが、手動での操作も可能です。
  - **コマンド例**:
    ```sql
    BEGIN
      DBMS_STATS.GATHER_TABLE_STATS('schema_name', 'table_name');
    END;
    ```

### Amazon RDS for SQL Server
- **コマンド**: `UPDATE STATISTICS`
  - SQL Serverでは、`UPDATE STATISTICS` コマンドを使って統計情報を更新します。これにより、テーブルやインデックスの統計情報が最新の状態に保たれます。
  - **コマンド例**:
    ```sql
    UPDATE STATISTICS my_table; -- 特定のテーブルの統計情報を更新
    ```

### Amazon RDS for Azure SQL Database
- **コマンド**: `UPDATE STATISTICS`
  - Azure SQL DatabaseでもSQL Serverと同様に、`UPDATE STATISTICS` コマンドを使用して統計情報を更新します。
  - **コマンド例**:
    ```sql
    UPDATE STATISTICS my_table; -- 特定テーブルの統計情報を更新
    ```

---


## まとめ

- 統計情報の更新は、データベースのパフォーマンス維持とシステムの安定性において重要な役割を果たします。特に、大量データが日々更新されるシステムでは、適切なタイミングで統計情報を更新することがクエリパフォーマンスを最大限に引き出す鍵となります。
  
- 自動更新と手動更新を併用することで、業務のニーズやシステムの負荷に応じた柔軟な運用が可能です。自動更新はメンテナンスの手間を減らし、手動更新はバッチ処理や特定のテーブルに対して柔軟に対応できるメリットがあります。
  
- データベースメンテナンスとして、自動更新スケジュールの設定を導入し、クエリ性能を改善しました。


- 統計情報の更新を効果的に管理することで、システム全体の効率を向上させることが可能です。今後はデータの増加にも柔軟に対応し、より効率的なメンテナンス方法を追求していくことが課題となります。