SQL Server はクエリの実行時には 統計情報 を使用してクエリの実行プランを生成しています。
統計情報は、以下のような情報で構成されており統計情報の作成を行うテーブルのデータを参照して情報を作成する必要があります。
- ヒストグラム: 最大 200 の区間で構成されたデータの分布情報
- 密度ベクトル: データの重複状況 (どれだけユニークなデータが含まれているか)
統計情報を更新する際に実データに対しての検索が行われますがどのようにデータ取得が行われているかについてまとめておきたいと思います。
統計情報の更新時に実行されているクエリ
統計情報の更新 (手動 or 自動) を実行した際に実行されるクエリは拡張イベントで「sp_statement_completed」を取得することで確認することができます。
実際には次のようなクエリが実行されています。
SELECT StatMan([SC0], [SC1], [SB0000]) FROM ( SELECT TOP 100 PERCENT [SC0], [SC1], step_direction([SC0]) over ( order by NULL ) AS [SB0000] FROM ( SELECT [no] AS [SC0], [time] AS [SC1] FROM [frontdoor].[accesslog2] TABLESAMPLE SYSTEM (5.249378e -01 PERCENT) WITH (READUNCOMMITTED) ) AS _MS_UPDSTATS_TBL_HELPER ORDER BY [SC0], [SC1], [SB0000] ) AS _MS_UPDSTATS_TBL OPTION (MAXDOP 16)
このクエリを確認するといくつかのポイントがあります。
- 「READUNCOMMITTED」で実行されており検索時のロック競合を軽減している
- 「TABLESAMPLE」を使用してデータのサンプリングが行われている
- MAXDOP は最大 16 で実行され、インスタンス or DB レベルで MAXDOP を指定している場合は 16 を最大値として指定した値の中で上限が設定される
基本形としてはこのようなクエリで実行されています。
パーティショニングしているテーブルについては 増分統計 を使用することでパーティション単位で統計情報を作成することができます。
増分統計を利用する場合は次のようにパーティション単位で統計情報の更新が行われるため、検索範囲をさらに限定的 ($PARTITOIN を使用した特定パーティションの検索) にすることができます。
SELECT StatMan([SC0], [SC1], [SB0000]) FROM ( SELECT TOP 100 PERCENT [SC0], [SC1], step_direction([SC0]) over ( order by NULL ) AS [SB0000] FROM ( SELECT [no] AS [SC0], [time] AS [SC1] FROM [frontdoor].[accesslog] TABLESAMPLE SYSTEM (5.348244e -01 PERCENT) WITH (READUNCOMMITTED) WHERE $PARTITION. [PF_accesslog]([time]) = 6 ) AS _MS_UPDSTATS_TBL_HELPER ORDER BY [SC0], [SC1], [SB0000] ) AS _MS_UPDSTATS_TBL OPTION (MAXDOP 16)
通常は、TABLESAMPLE を使用して自動的に算出されたサンプリングレートによってデータのサンプリングが行われますが、FULLSCAN や、SAMPLE を使用した場合は指定した設定に応じたサンプリングレートでデータの検索が行われます。