対象者:SQL Server 2016 (13.x) およびそれ以降のバージョン
Azure SQL Database
Azure SQL Managed Instance
SQL Database in Microsoft Fabric
現在の SQL Server データベース内の指定されたデータベース オブジェクト (テーブルまたはインデックス付きビュー) の統計ヒストグラムを返します。
DBCC SHOW_STATISTICS WITH HISTOGRAM と似ています。
Note
この DMF は、SQL Server 2016 (13.x) SP1 CU2 以降で使用できます。
構文
sys.dm_db_stats_histogram (object_id , stats_id)
引数
object_id
統計の 1 つのプロパティが要求される、現在のデータベース内のオブジェクトの ID。 object_ID は intです。
stats_id
指定した object_idの統計の ID。 統計 ID は、 sys.stats 動的管理ビューから取得できます。 stats_id は intです。
返されるテーブル
| 列名 | データ型 | 説明 |
|---|---|---|
object_id |
int | 統計オブジェクトのプロパティを返す対象であるオブジェクト (テーブルまたはインデックス付きビュー) の ID。 |
stats_id |
int | 統計オブジェクトの ID。 テーブルまたはインデックス付きビュー内で一意です。 詳細については、 sys.stats を参照してください。 |
step_number |
int | ヒストグラムの区間の数。 |
range_high_key |
sql_variant | ヒストグラム区間の上限の列値。 この列値はキー値とも呼ばれます。 |
range_rows |
real | ヒストグラム区間内 (上限は除く) に列値がある行の予測数。 |
equal_rows |
real | ヒストグラム区間の上限と列値が等しい行の予測数。 |
distinct_range_rows |
bigint | ヒストグラム区間内 (上限は除く) にある個別の列値を持つ行の予測数。 |
average_range_rows |
real | 上限を除く、ヒストグラムのステップ内で重複する列の値を持つ行の数の平均値(RANGE_ROWS / DISTINCT_RANGE_ROWSのDISTINCT_RANGE_ROWS > 0)。 |
解説
sys.dm_db_stats_histogram の結果セットは、同様の情報を DBCC SHOW_STATISTICS WITH HISTOGRAM に返し、さらに object_id、stats_id、 および step_number も含まれます。
列 range_high_key はsql_variantデータ型であるため、述語が文字列以外の定数と比較する場合は、 CAST または CONVERT を使用する必要があります。
ヒストグラム
ヒストグラムでは、データセットの個別の値ごとに出現頻度を測定します。 クエリ オプティマイザーでは、統計オブジェクトの最初のキー列の列値に基づいてヒストグラムを計算し、行を統計的にサンプリングするかテーブルまたはビュー内のすべての行でフル スキャンを実行することによって列値を選択します。 サンプリングされた一連の行からヒストグラムが作成された場合、行の数と個別の値の数に対する格納された合計は見積もりであり、整数である必要はありません。
ヒストグラムを作成するには、クエリ オプティマイザーで列値を並べ替え、個別の列値ごとに一致する値の数を計算し、列値を最大 200 の連続したヒストグラム区間に集計します。 各区間には、上限の列値までの列値の範囲が含まれます。 この範囲には、境界値の間 (境界値自体は除く) のすべての有効な列値が含まれます。 格納される最小の列値は、最初のヒストグラム区間の上限境界値になります。
次の図は、6 つの区間があるヒストグラムを示しています。 最初の上限境界値の左側にある領域が最初の区間です。
ヒストグラムの各区間は、以下のように表されます。
太線は、上限境界値 (range_high_key) およびその出現回数 (equal_rows) を表します。
range_high_key の左にある領域は、列値の範囲、およびそれぞれの列値の平均出現回数 (average_range_rows) を表します。 最初のヒストグラム区間の average_range_rows は常に 0 です。
点線は、範囲内にある個別の値の総数 (distinct_range_rows) および範囲内の値の総数 (range_rows) を推定するために使用されるサンプリングされた値を表します。 クエリ オプティマイザーは 、range_rows と distinct_range_rows を使用して average_range_rows を計算し、サンプリングされた値を格納しません。
クエリ オプティマイザーでは、統計的有意性に応じてヒストグラム区間を定義します。 区間幅を最大にするアルゴリズムを使用して境界値の差を最大にし、ヒストグラムの区間の数を最小限に抑えます。 区間の最大数は 200 です。 ヒストグラムの区間の数は、境界点が 200 より少ない列でも、個別の値の数より少なくなることがあります。 たとえば、個別の値が 100 個ある列のヒストグラムの境界点が 100 より少なくなる場合もあります。
アクセス許可
ユーザーが統計列に対する選択権限を持っているか、ユーザーがテーブルを所有しているか、ユーザーが sysadmin 固定サーバー ロール、 db_owner 固定データベース ロール、または固定データベース ロール db_ddladmin メンバーである必要があります。
例
A. 基本的な例
次の例では、基本テーブルを作成して設定します。 次に、Region_Name 列に統計を作成します。
CREATE TABLE Region
(
Region_ID INT IDENTITY PRIMARY KEY,
Region_Name VARCHAR (120) NOT NULL
);
INSERT Region (Region_Name)
VALUES ('Canada'), ('Denmark'), ('Iceland'), ('Peru');
CREATE STATISTICS Region_Stats ON Region(Region_Name);
主キーは stat_id 数値 1 を占めているため、sys.dm_db_stats_histogram 数値 2 の stat_id を呼び出して、Region テーブルの統計ヒストグラムを返します。
SELECT * FROM sys.dm_db_stats_histogram(OBJECT_ID('Region'), 2);
B. 便利なクエリ
SELECT hist.step_number,
hist.range_high_key,
hist.range_rows,
hist.equal_rows,
hist.distinct_range_rows,
hist.average_range_rows
FROM sys.stats AS s
CROSS APPLY sys.dm_db_stats_histogram(s.[object_id], s.stats_id) AS hist
WHERE s.[name] = N'<statistic_name>';
C: 便利なクエリ
次の例では、列 Region に述語があるテーブル Region_Name から選択します。
SELECT * FROM Region
WHERE Region_Name = 'Canada';
次の例では、上記のクエリの述語と一致するヒストグラム ステップについて、テーブル Region と列 Region_Name に対して以前に作成した統計情報を確認します。
SELECT ss.name,
ss.stats_id,
shr.steps,
shr.rows,
shr.rows_sampled,
shr.modification_counter,
shr.last_updated,
sh.range_rows,
sh.equal_rows
FROM sys.stats AS ss
INNER JOIN sys.stats_columns AS sc
ON ss.stats_id = sc.stats_id
AND ss.object_id = sc.object_id
INNER JOIN sys.all_columns AS ac
ON ac.column_id = sc.column_id
AND ac.object_id = sc.object_id
CROSS APPLY sys.dm_db_stats_properties(ss.object_id, ss.stats_id) AS shr
CROSS APPLY sys.dm_db_stats_histogram(ss.object_id, ss.stats_id) AS sh
WHERE ss.[object_id] = OBJECT_ID('Region')
AND ac.name = 'Region_Name'
AND sh.range_high_key = CAST ('Canada' AS CHAR (8));