TECHNOLOGY

FAQ (よくある質問)

対象バージョン : SQL Anywhere (Adaptive Server Anywhere) version 9 以降
対象OS : 全て

QUESTION ( SQ0809079 )

統計情報はいつ、どのように作成されるか

SQL Anywhereのクエリプランは統計情報に依存して変化するということですが、統計情報とはいつ、どのように作成されているのでしょうか?
また、統計情報が陳腐化した場合に最適でないプランが選択されるということですが、どのような原因で統計情報が陳腐化するのでしょうか。

ANSWER

[統計情報の作成されるタイミングと条件]

SQL Anywhereは、以下のような場合に統計情報を作成します。

a. INSERT、UPDATE、DELETE文によりデータが変更されることで統計情報の作成/更新が行なわれます。
この時作成される統計情報は、上記のSQL文により変更されたデータに存在する全てのカラムの値から作成されます。

この統計情報の更新は毎回行なわれるのではなく、上記のSQL文によって変更されるロー数がテーブルの統計を更新する最小ロー数(しきい値)を超えた場合に行なわれます。
しきい値はSQL文が実行されたテーブルに存在しているローの数に基づき決定されます。(詳しくは以下の計算式に基づきます。)

5 × ( log10( テーブルに存在しているローの数 + 1 ) )

例えば、100ローのテーブルでは、10ロー以上の更新が行なわれた場合に、統計情報の更新が行なわれます。

b. クエリ(SELECT、INSERT FROM SELECT、UPDATE、DELETE文) の実行時に統計情報の作成/更新が行なわれます。
この時作成される統計情報は、クエリ中の述部(WHERE、HAVING、ON句に記述される条件)を構成するカラムの値について統計を収集し、述部に一致する値についてのみ更新が行われます。
(オプティマイザが推定したローの数と、実際に検索されたローの数を比較して、統計情報の値を調整します。)

c. CREATE STATISTICS 文の実行時に統計情報の作成が行なわれます。
この文ではテーブルに存在する全てのカラムに対する統計情報が新規で作成されます。また、テーブルの最小ロー数などのしきい値に関わり無く統計情報の作成が行なわれます。

d. LOAD TABLE 文の実行時に統計情報の作成/更新が行なわれます。
この文ではオプションで統計を作成するカラムを制限できますが、基本的には全てのカラムに対して統計が作成されます。
但し、既存のローが存在するが、統計情報が存在していないテーブルに対してLOAD TABLE文を実行した場合には、統計情報は作成されません。

e. CREATE INDEX 文の実行時に統計情報の作成/更新が行なわれます。
この文ではINDEXを構成するカラムに対してのみ統計が作成/更新されます。

[統計情報が陳腐化する一般的な原因]

a. 単一ローの挿入を繰り返し、大量のデータを短いスパンで追加した。
基本的な単一のローを挿入するINSERT文では統計情報は変化しません。
(例:INSERT INTO テーブル VALUES(値リスト))

b. (少量の)ローの追加や更新、削除を繰り返し、大量のデータを短いスパンで変更した。
前述の[統計情報の作成されるタイミング]のa.で説明した最小ロー数(しきい値)以下のロー数のデータ変更が行われた場合には、統計情報は変化しません。(カーソルを使用した更新などもこれに該当します。)

c. LOAD TABLE文の実行時に、ロード先のテーブルに既存のデータがあるが、統計情報が存在していなかった。
前述の[統計情報の作成されるタイミング]のd.で説明したように、新規テーブルへの LOAD TABLE 文の実行時には、ロードされるデータによって統計情報が作成されますが、テーブルに既存のデータがあるにも関わらず、統計情報が存在していない場合、LOAD TABLE 文の実行では統計情報の作成は行われません。

d. (大量の)トランザクションを実行後にロールバックを行なった。
ロールバックは、トランザクションの実行により更新された統計情報を取り消しません。この為、トランザクションがコミットされた場合と同様に統計情報が変化します。

※ 上記のような状況で変更されたローの情報が統計情報に反映されるのは、[統計情報の作成されるタイミングと条件]のb.で説明したクエリの実行時や c.のCREATE STATISTICS 文の実行時となります。
この為、大量のデータが短いスパンで追加、更新、または削除されて以来、実行されたクエリが少ない場合に、統計情報の陳腐化によるパフォーマンスの低下が発生する可能性がございます。

[統計情報が陳腐化したことによるパフォーマンス低下の回避方法]

a. 上記の一般的な原因に記述したような、最小ロー数(しきい値)以下のデータ追加/更新/削除が繰り返し実行される、統計情報の作成/更新が行われないような処理が定期的に発生する場合は、そのタイミングに合わせて統計情報の再作成を明示的に行います。

例えば、夜間バッチ等で、データの追加/更新/削除等を行った際に統計情報の陳腐化が発生している場合、一連の処理の最後に CREATE STATISTICS文を実行して統計情報の再作成を行います。

b. または、インデックス・ヒントを使用してオプティマイザを無効にし、常に特定のインデックスを使用するよう要求したり、明示的な選択性推定を指定し、オプティマイザに統計情報とは異なる情報を与えることによって、陳腐化した統計情報を使用させないという方法もございます。
この方法は、統計情報が陳腐化するタイミングが不明確である場合や、統計情報の再作成が困難である場合などにご検討下さい。

・ インデックス・ヒントの詳細につきましては、以下のオンラインマニュアルを参照下さい。
http://www.ianywhere.com/developer/product_manuals/sqlanywhere/0902/ja/html/dbrfja9/00000419.htm
・ 明示的な選択性推定の詳細につきましては、以下のオンラインマニュアルをご参照下さい。
http://www.ianywhere.com/developer/product_manuals/sqlanywhere/0902/ja/html/dbrfja9/00000040.htm
[注意事項]

 上記、[統計情報が陳腐化する一般的な原因]で説明したような処理を行った場合を除いて、CREATE STATISTICS 文を定期的に実行するといった運用は基本的に必要ございません。
通常は、クエリの実行により、統計情報は十分にメンテナンスされます。

 また、CREATE STATISTICS 文はテーブル全体の統計情報を作り直しますが、この時に作成される統計は、テーブル全体に対して均等な間隔でのデータの分布状況を分析した情報となります。
この場合、テーブルのデータに局所的な偏りがありますと、その統計情報は(大局的には正しいと言えるのですが)、ピンポイントでの参照において実際のデータの分布と大幅に異なっている可能性がございます。

逆にクエリ実行の際に作成される統計情報は、クエリの対象となる特定の範囲のデータ分布の情報を収集して統計へ反映する為、局所的なデータの偏りもフォローされ、精度の高い情報が得られる可能性がございます。

この為、特にパフォーマンスの問題が無い状況で、CREATE STATISTICS 文を実行し、統計情報の再作成を行いますと、却ってパフォーマンスの低下を招く可能性もございますのでご注意ください。