神谷 雅紀
Escalation Engineer
インデックスの再構築や再構成を実行中にキャンセル (中断) した場合については、インデックス再構築と再構成の違いで触れていますが、統計情報を更新している最中に処理をキャンセルした場合はどうなるのかといった質問がありましたので、今回は、統計情報の更新処理をキャンセルした場合の動作について説明します。
※ 以下の動作は SQL Server 2012 のものです。基本的には他のバージョンでも同じであると思われますが、明示的な確認は行っていません。
統計情報更新をキャンセルした場合の動作
統計情報の更新は、各統計情報ごとにひとつのトランザクションとして実行されます。ある統計情報を更新している最中にキャンセル (中断) した場合には、その統計情報を更新しているトランザクションも中断され、ロールバックされます。結果として、統計情報は更新前の状態に戻ります。
この動作は、拡張イベントの transactions.sql_transaction や SQL Trace の SQL Transaction イベントで確認することができます。
UPDATE STATISTICS ステートメントの場合
UPDATE STATISTICS は、個々の統計情報を指定して実行することも、テーブルを指定して実行することもできます。テーブルを指定して実行した場合には、そのテーブルに属するすべての統計情報が更新されます。
テーブル名のみを指定した UPDATE STATISTICS の実行をキャンセルした場合のキャンセル後の状態は、キャンセルよりも前に更新が完了している統計情報については更新後の状態、キャンセル時点で更新中であった統計情報、および、まだ更新が開始されていなかった統計情報は、更新前の状態になります。
テーブル名のみではなく統計名またはインデックス名も指定して実行した場合には、UPDATE STATISTICS をキャンセルすると、統計情報は更新前の状態に戻ります。
ただし、キャンセルが、統計情報更新トランザクションは完了しているものの、UPDATE STATISTICS ステートメントはまだ完了していないタイミングになることもありえます。その場合は、UPDATE STATISTICS をキャンセルしても統計情報は更新された状態になります。
統計情報の自動更新の場合
自動更新の場合も UPDATE STATISTICS の場合と同様に、統計情報更新トランザクションが実行されている最中にキャンセルした場合には、トランザクションはロールバックされ、更新前の状態に戻ります。
自動更新の場合は、明示的に UPDATE STATISTICS を実行する場合とは異なり、統計情報を参照するステートメントの実行時に更新されることから、統計情報更新のキャンセルは、同期更新であれば、それを起動したステートメントのキャンセル時に発生することになります。非同期更新の場合は、統計情報更新タスクがキューにポストされるのみで、実際の更新はバックグラウンドタスクによって実行されます。バックグラウンドタスクは、何らかのエラーや SQL Server のシャットダウンなどにより中断を余儀なくされた場合を除いて、処理をキャンセルしません。
統計情報が更新されるのは、ステートメントの最適化フェーズです。最適化が終了し、実行フェーズに入った後にステートメントがキャンセルされても、統計情報は更新後の状態になります。
更新対象となる統計情報は、ステートメントが最適化されている最中に参照される統計情報のうち、自動更新の閾値を超えているもののみです。
※ 統計情報は、これから参照するデータがどの程度あるのかを推測するために使用されるものです。そのため、統計情報の更新のきっかけとなるのは、データを更新する時ではなく、データを参照する時です。行の追加では統計情報の自動更新は行われません。更新や削除でも、更新や削除の対象となる行を選ぶためには統計情報は必要になりますが、実際にデータを書き換えるためには必要になりません。