【DB】統計情報について

統計情報とは?

 * テーブル、インデックスなどがどのような状態なのかを表している情報。

 * データ量
  => テーブルにデータが何件格納されているか
  => 1行の平均サイズは、どの位なのか
 * データの分布状況
  => テーブル項目にはどのような値が多く格納されているか
など

統計情報は何のために使うのか

 * DBのオプティマイザは複数の実行プランを作成し、その中で最適な実行プランを選択するのだが、
  その選択基準となるのが、統計情報である。

※なお、オプティマイザや実行プランの詳細な説明については、以下の記事を参照のこと。
http://blogs.yahoo.co.jp/dk521123/28850809.html

統計情報更新の必要性

 * 統計情報が、DBの現状とは異なる状況を表している場合、パフォーマンスが悪い実行プランを選択し
  処理遅延を起こす可能性がある点

実データが1億件で、その中から5件取得するSQLを実行したとする...

仮に、統計情報が古く、対象テーブルに対して5件しか格納されていないという統計情報になっていた場合、
DBのオプティマイザは「どうせ5件しかないんだから、5件取得するのには、インデックスなんか使わずに
フルスキャンでええやろ」と判断してしまう可能性がある。
 →しかし、実データは1億件なので、この結果、パフォーマンスが悪くなる。

この例の原因は、統計情報が古いので、更新していれば、正しい実行プランを選択する可能性が高くなる

使用上の注意

 * デフォルトは、自動更新になっている。
 * 時には、手動で行う必要がある。詳細は以下を参照のこと。
http://blogs.msdn.com/b/jpsql/archive/2012/04/19/on.aspx

統計情報更新の適切なタイミング

 以下の参考文献は、Oracleが対象だが他のDBにも同じことが言えそうなので、メモっとく。

■要約
データの特性によって、どのようなタイミングで統計情報を収集すればよいかが決まる。
 => そのため、まずは対象テーブルが、どのような特性に分類されるのかを知る必要がある

[1] データ量がほぼ一定

 例えば、あまり変更がないマスターテーブル等?
 => 定期的に統計情報を取得する必要はない
 => DBの設定で自動統計収集に任せて良さそう

[2] 一貫した増加傾向

 例えば、長期間に保存して置かなければならない注文テーブル等?
 => 定期的に統計情報を更新する必要がある

※注意
 統計情報の更新には、CPUなどハードウェアリソースを使用するため、
業務処理が少ない時間帯(例えば、夜間や土日・祝日など)にバッチ処理などで更新した方がいい

[3] 一定間隔での増加/減少の繰り返し

 例えば、バッチ処理を行うなど、一定間隔での増加/減少を繰り返すテーブル等
 => データの特性として、実データと統計情報の乖離が発生し易い
 => データ量が最大になるタイミングで更新するといい

[4] 不確定な変動

 例えば、景気などの影響する部品などの発注テーブル?等
 => データの特性として、実データと統計情報の乖離が発生し易い
  (ただし、[3]とは異なり、データ量が最大になるタイミングが分からない)
 => 自動統計収集を無効化する
 => 記事には、以下のように書いてあるけど、現実的にはそもそも予想できないのだから難しそう
    動的サンプリングは、Oracleの機能(?)だから他のDBでは難しい??
 * 将来的な表の最大件数を再現したテストデータで統計情報を取得し、固定化することで対応
  * 本番環境に近いデータ分布も意識してテストデータを作成する必要
 * テストデータを用意することが難しい場合は、動的サンプリングを使用することを検討

参考文献

http://enterprisezine.jp/dbonline/detail/4253
http://oracletech.jp/products/pickup/000371.html

関連記事

SQL Server のパフォーマンスをあげることを考える

http://blogs.yahoo.co.jp/dk521123/28530905.html

SQL Server の統計情報

http://blogs.yahoo.co.jp/dk521123/30439950.html