統計Statistics

適用対象: ○SQL Server ○Azure SQL Database ○Azure SQL Data Warehouse ○Parallel Data WarehouseAPPLIES TO: yesSQL Server yesAzure SQL Database yesAzure SQL Data Warehouse yesParallel Data Warehouse

クエリ オプティマイザーでは、クエリのパフォーマンスを向上させるクエリ プランを作成するために統計を使用します。The Query Optimizer uses statistics to create query plans that improve query performance. ほとんどのクエリでは、高品質のクエリ プランに必要な統計がクエリ オプティマイザーによって既に生成されていますが、最適な結果を得るために追加の統計情報を作成したり、クエリのデザインを変更したりする必要がある場合もあります。For most queries, the Query Optimizer already generates the necessary statistics for a high quality query plan; in some cases, you need to create additional statistics or modify the query design for best results. このトピックでは、クエリ最適化に関する統計の概念と、それを効果的に使用するためのガイドラインについて説明します。This topic discusses statistics concepts and provides guidelines for using query optimization statistics effectively.

コンポーネントおよび概念Components and Concepts

統計Statistics

クエリ最適化に関する統計は、テーブルまたはインデックス付きビューの 1 つまたは複数の列の値の分布に関する統計情報を格納するバイナリ ラージ オブジェクト (BLOB) です。Statistics for query optimization are binary large objects (BLOBs) that contain statistical information about the distribution of values in one or more columns of a table or indexed view. クエリ オプティマイザーでは、これらの統計を使用してクエリ結果のカーディナリティ、つまり行数を推定します。The Query Optimizer uses these statistics to estimate the cardinality, or number of rows, in the query result. これらのカーディナリティの推定に基づいて、クエリ オプティマイザーでは高品質なクエリ プランを作成できます。These cardinality estimates enable the Query Optimizer to create a high-quality query plan. たとえば、ご利用の述語によっては、クエリ オプティマイザーがカーディナリティの推定を使用して、リソース消費の多い Index Scan 操作ではなく Index Seek 操作を選択することがあります。そうすることで、クエリのパフォーマンスが高まります。For example, depending on your predicates, the Query Optimizer could use cardinality estimates to choose the index seek operator instead of the more resource-intensive index scan operator, if doing so improves query performance.

統計オブジェクトは 1 つ以上のテーブル列で構成されるリストごとに作成され、それぞれに最初の列の値の分布を示すヒストグラムが含まれます。Each statistics object is created on a list of one or more table columns and includes a histogram displaying the distribution of values in the first column. 複数列の統計オブジェクトには、さらに、列間の値の相関関係に関する統計情報も格納されます。Statistics objects on multiple columns also store statistical information about the correlation of values among the columns. これらの相関関係の統計情報 ( 密度) は、個別の列値を持つ行の数から得られます。These correlation statistics, or densities, are derived from the number of distinct rows of column values.

ヒストグラムHistogram

ヒストグラムでは、データセットの個別の値ごとに出現頻度を測定します。A histogram measures the frequency of occurrence for each distinct value in a data set. クエリ オプティマイザーでは、統計オブジェクトの最初のキー列の列値に基づいてヒストグラムを計算し、行を統計的にサンプリングするかテーブルまたはビュー内のすべての行でフル スキャンを実行することによって列値を選択します。The query optimizer computes a histogram on the column values in the first key column of the statistics object, selecting the column values by statistically sampling the rows or by performing a full scan of all rows in the table or view. サンプリングされた行のセットからヒストグラムを作成する場合、格納される行の総数および個別の値の数は推定値であり、必ずしも整数にはなりません。If the histogram is created from a sampled set of rows, the stored totals for number of rows and number of distinct values are estimates and do not need to be whole integers.

注意

SQL ServerSQL Server のヒストグラムは、単一の列 (統計オブジェクトのキー列のセットの最初の列) に対してのみ作成されます。Histograms in SQL ServerSQL Server are only built for a single column-the first column in the set of key columns of the statistics object.

ヒストグラムを作成するには、クエリ オプティマイザーで列値を並べ替え、個別の列値ごとに一致する値の数を計算し、列値を最大 200 の連続したヒストグラム区間に集計します。To create the histogram, the query optimizer sorts the column values, computes the number of values that match each distinct column value and then aggregates the column values into a maximum of 200 contiguous histogram steps. 各ヒストグラム区間には、列値の範囲と上限の列値が順番に含まれます。Each histogram step includes a range of column values followed by an upper bound column value. この範囲には、境界値の間 (境界値自体は除く) のすべての有効な列値が含まれます。The range includes all possible column values between boundary values, excluding the boundary values themselves. 格納される最小の列値は、最初のヒストグラム区間の上限境界値になります。The lowest of the sorted column values is the upper boundary value for the first histogram step.

具体的には、SQL ServerSQL Server は、次の 3 つの区間で、並べ替えられた列値のセットからヒストグラムを作成します。In more detail, SQL ServerSQL Server creates the histogram from the sorted set of column values in three steps:

  • ヒストグラムの初期化:最初の区間で、並べ替えられたセットの先頭から始まる値のシーケンスが処理され、range_high_keyequal_rowsrange_rowsdistinct_range_rows の最大 200 個の値が収集されます (この区間の間、range_rowsdistinct_range_rows は常にゼロです)。Histogram initialization: In the first step, a sequence of values starting at the beginning of the sorted set is processed, and up to 200 values of range_high_key, equal_rows, range_rows, and distinct_range_rows are collected (range_rows and distinct_range_rows are always zero during this step). 最初の区間は、すべての入力が使用されたとき、または 200 個の値が見つかったときに終了します。The first step ends either when all input has been exhausted, or when 200 values have been found.
  • バケットのマージを使用したスキャン:2 つ目の手順では、統計キーの先頭の列から追加された各値が並び順で処理されます。連続する各値は最後の範囲に追加されるか、末尾に新しい範囲が作成されます (これは、入力値が並べ替えられているため可能です)。Scan with bucket merge: Each additional value from the leading column of the statistics key is processed in the second step, in sorted order; each successive value is either added to the last range or a new range at the end is created (this is possible because the input values are sorted). 新しい範囲が作成されると、既存の隣接する範囲の 1 組が 1 つの範囲に折りたたまれます。If a new range is created, then one pair of existing, neighboring ranges is collapsed into a single range. 情報の損失を最小限に抑えるために、この範囲の組が選択されます。This pair of ranges is selected in order to minimize information loss. この方法では、区間幅を最大にするアルゴリズムを使用して境界値の差を最大にし、ヒストグラムの区間の数を最小限に抑えます。This method uses a maximum difference algorithm to minimize the number of steps in the histogram while maximizing the difference between the boundary values. 範囲を折りたたんだ後の手順の数は、この手順全体で 200 個のままです。The number of steps after collapsing ranges stays at 200 throughout this step.
  • ヒストグラムの統合:3 番目の区間では、失われる情報の量が少なければ、より多くの範囲が折りたたまれる可能性があります。Histogram consolidation: In the third step, more ranges may be collapsed if a significant amount of information is not lost. ヒストグラムの区間の数は、境界点が 200 より少ない列でも、個別の値の数より少なくなることがあります。The number of histogram steps can be fewer than the number of distinct values, even for columns with fewer than 200 boundary points. そのため、列に 200 を超える一意の値が含まれていても、ヒストグラムの区間の数は 200 未満となることがあります。Therefore, even if the column has more than 200 unique values, the histogram may have less than 200 steps. 一意の値のみで構成される列の場合、統合されたヒストグラムには最小で 3 つの区間が存在します。For a column consisting of only unique values, then the consolidated histogram will have a minimum of three steps.

注意

fullscan ではなくサンプルを使用してヒストグラムが作成されている場合、equal_rowsrange_rowsdistinct_range_rowsaverage_range_rows の値は推定されます。そのため、これらの値は整数である必要はありません。If the histogram has been built using a sample rather than fullscan, then the values of equal_rows, range_rows, and distinct_range_rows and average_range_rows are estimated, and therefore they do not need to be whole integers.

次の図は、6 つの区間があるヒストグラムを示しています。The following diagram shows a histogram with six steps. 最初の上限境界値の左側にある領域が最初の区間です。The area to the left of the first upper boundary value is the first step.

上記のヒストグラムの各区間は、以下のように表されます。For each histogram step above:

  • 太線は、上限境界値 (range_high_key) およびその出現回数 (equal_rows) を表します。Bold line represents the upper boundary value (range_high_key) and the number of times it occurs (equal_rows)

  • range_high_key の左にある領域は、列値の範囲、およびそれぞれの列値の平均出現回数 (average_range_rows) を表します。Solid area left of range_high_key represents the range of column values and the average number of times each column value occurs (average_range_rows). 最初のヒストグラム区間の average_range_rows は常に 0 です。The average_range_rows for the first histogram step is always 0.

  • 点線は、範囲内にある個別の値の総数 (distinct_range_rows) および範囲内の値の総数 (range_rows) を推定するために使用されるサンプリングされた値を表します。Dotted lines represent the sampled values used to estimate total number of distinct values in the range (distinct_range_rows) and total number of values in the range (range_rows). クエリ オプティマイザーでは、range_rows および distinct_range_rows を使用して average_range_rows を計算します。サンプリングされた値は格納されません。The query optimizer uses range_rows and distinct_range_rows to compute average_range_rows and does not store the sampled values.

密度ベクトルDensity Vector

密度とは、特定の列または列の組み合わせにおける重複の数に関する情報であり、1/(個別の値の数) の式で計算されます。Density is information about the number of duplicates in a given column or combination of columns and it is calculated as 1/(number of distinct values). クエリ オプティマイザーでは、同一のテーブルまたはインデックス付きビューから複数の列を返すクエリに対するカーディナリティの推定を向上させるために密度を使用します。The query optimizer uses densities to enhance cardinality estimates for queries that return multiple columns from the same table or indexed view. 密度が減少するにつれて、値の選択度が高くなります。As density decreases, selectivity of a value increases. たとえば、車を表すテーブルの場合、同メーカーの車がいくつもあります。ただし、VIN (車両番号) はそれぞれの車両固有のものです。For example, in a table representing cars, many cars have the same manufacturer, but each car has a unique vehicle identification number (VIN). VIN 上のインデックスは、製造元でのインデックスより選択度が高くなります。これは VIN の密度が製造元の場合より低いからです。An index on the VIN is more selective than an index on the manufacturer, because VIN has lower density than manufacturer.

注意

頻度とは、統計オブジェクトの最初のキー列における各個別値の発生に関する情報であり、"行数 * 密度" の式で計算されます。Frequency is information about the occurrence of each distinct value in the first key column of the statistics object, and is calculated as row count * density. 最大頻度 1 は、一意の値を持つ列で確認できます。A maximum frequency of 1 can be found in columns with unique values.

密度ベクトルには、統計オブジェクトの列のプレフィックスごとに 1 つの密度が格納されます。The density vector contains one density for each prefix of columns in the statistics object. たとえば、統計オブジェクトに CustomerIdItemIdPrice というキー列がある場合、以下の列プレフィックスごとに密度が計算されます。For example, if a statistics object has the key columns CustomerId, ItemId and Price, density is calculated on each of the following column prefixes.

列プレフィックスColumn prefix 密度の計算対象Density calculated on
(CustomerId)(CustomerId) CustomerId の値が一致する行Rows with matching values for CustomerId
(CustomerId, ItemId)(CustomerId, ItemId) CustomerId および ItemId の値が一致する行Rows with matching values for CustomerId and ItemId
(CustomerId, ItemId, Price)(CustomerId, ItemId, Price) CustomerId、ItemId、および Price の値が一致する行Rows with matching values for CustomerId, ItemId, and Price

フィルター選択された統計情報Filtered Statistics

適切に定義されたデータのサブセットから選択するクエリでは、フィルター選択された統計情報を使用するとクエリのパフォーマンスを向上させることができます。Filtered statistics can improve query performance for queries that select from well-defined subsets of data. フィルター選択された統計情報では、統計情報に含まれるデータのサブセットを選択するためにフィルター述語を使用します。Filtered statistics use a filter predicate to select the subset of data that is included in the statistics. 統計情報を適切にフィルター選択すると、テーブル全体の統計情報を使用する場合と比べて、クエリ実行プランが向上します。Well-designed filtered statistics can improve the query execution plan compared with full-table statistics. フィルター述語の詳細については、「CREATE STATISTICS (Transact-SQL)」を参照してください。For more information about the filter predicate, see CREATE STATISTICS (Transact-SQL). フィルター選択された統計情報を作成する場合の詳細については、このトピックの「 統計を作成する場合 」を参照してください。For more information about when to create filtered statistics, see the When to Create Statistics section in this topic.

統計オプションStatistics Options

統計の作成と更新のタイミングおよび方法を指定するための 3 つのオプションを設定できます。There are three options that you can set that affect when and how statistics are created and updated. これらのオプションは、データベース レベルでのみ設定されます。These options are set at the database level only.

AUTO_CREATE_STATISTICS オプションAUTO_CREATE_STATISTICS Option

統計の自動作成オプション AUTO_CREATE_STATISTICS がオンの場合、クエリ プランのカーディナリティの推定を向上させるために、クエリ オプティマイザーによってクエリ述語内の個々の列に関する統計が必要に応じて作成されます。When the automatic create statistics option, AUTO_CREATE_STATISTICS is ON, the Query Optimizer creates statistics on individual columns in the query predicate, as necessary, to improve cardinality estimates for the query plan. これらの 1 列ずつの統計は、既存の統計オブジェクトにまだヒストグラムがない列について作成されます。These single-column statistics are created on columns that do not already have a histogram in an existing statistics object. AUTO_CREATE_STATISTICS オプションでは、インデックスに対する統計を作成するかどうかは判断されません。The AUTO_CREATE_STATISTICS option does not determine whether statistics get created for indexes. また、フィルター選択された統計情報も生成されません。This option also does not generate filtered statistics. このオプションは、テーブル全体の 1 列ずつの統計にのみ適用されます。It applies strictly to single-column statistics for the full table.

AUTO_CREATE_STATISTICS オプションを使用した結果としてクエリ オプティマイザーによって統計が作成された場合、その統計名は _WA で始まります。When the Query Optimizer creates statistics as a result of using the AUTO_CREATE_STATISTICS option, the statistics name starts with _WA. 次のクエリを使用すると、クエリ オプティマイザーでクエリ述語列の統計が作成されたかどうかを判断できます。You can use the following query to determine if the Query Optimizer has created statistics for a query predicate column.

SELECT OBJECT_NAME(s.object_id) AS object_name,  
    COL_NAME(sc.object_id, sc.column_id) AS column_name,  
    s.name AS statistics_name  
FROM sys.stats AS s 
INNER JOIN sys.stats_columns AS sc  
    ON s.stats_id = sc.stats_id AND s.object_id = sc.object_id  
WHERE s.name like '_WA%'  
ORDER BY s.name;  

AUTO_UPDATE_STATISTICS オプションAUTO_UPDATE_STATISTICS Option

統計の自動更新オプション AUTO_UPDATE_STATISTICS がオンの場合、古くなっている可能性がある統計がクエリ オプティマイザーによって判断され、それらがクエリで使用されると更新されます。When the automatic update statistics option, AUTO_UPDATE_STATISTICS is ON, the Query Optimizer determines when statistics might be out-of-date and then updates them when they are used by a query. 挿入、更新、削除、またはマージの各操作によってテーブルまたはインデックス付きビューのデータの分布が変わると、統計は古くなったと判断されます。Statistics become out-of-date after insert, update, delete, or merge operations change the data distribution in the table or indexed view. クエリ オプティマイザーでは、統計が前回更新されてから発生したデータ変更の数をカウントし、その変更の数をしきい値と比較することで、統計が古くなっている可能性がないかを判断します。The Query Optimizer determines when statistics might be out-of-date by counting the number of data modifications since the last statistics update and comparing the number of modifications to a threshold. このしきい値は、テーブルまたはインデックス付きビューの行数に基づいて決められます。The threshold is based on the number of rows in the table or indexed view.

  • SQL Server 2014 (12.x)SQL Server 2014 (12.x) まで、SQL ServerSQL Server は変更された行の割合に基づくしきい値を使用します。Up to SQL Server 2014 (12.x)SQL Server 2014 (12.x), SQL ServerSQL Server uses a threshold based on the percent of rows changed. これには、テーブル内の行数は考慮されません。This is regardless of the number of rows in the table. しきい値は次のようになります。The threshold is:

    • 統計情報が評価された時点でテーブルのカーディナリティが 500 以下の場合、500 回変更されるたびに更新されます。If the table cardinality was 500 or less at the time statistics were evaluated, update for every 500 modifications.
    • 統計情報が評価された時点でテーブルのカーディナリティが 500 よりも大きい場合、500 プラス 20% の数の変更があるたびに更新されます。If the table cardinality was above 500 at the time statistics were evaluated, update for every 500 + 20 percent of modifications.
  • SQL Server 2016 (13.x)SQL Server 2016 (13.x) 以降で、データベースの互換性レベルが 130 未満の場合、SQL ServerSQL Server では、テーブル内の行数に基づいて調整された、より小さな値の動的な統計情報更新しきい値を使用します。Starting with SQL Server 2016 (13.x)SQL Server 2016 (13.x) and under the database compatibility level 130, SQL ServerSQL Server uses a decreasing, dynamic statistics update threshold that adjusts according to the number of rows in the table. これは、1,000 と現在のテーブルのカーディナリティの積の平方根として計算されます。This is calculated as the square root of the product of 1000 and the current table cardinality. たとえば、テーブルに 200 万行含まれている場合、計算は sqrt (1000 * 2000000) = 44721.359 となります。For example if your table contains 2 million rows, then the calculation is  sqrt (1000 * 2000000) = 44721.359. この変更により、大規模なテーブルの統計がより頻繁に更新されます。With this change, statistics on large tables will be updated more often. ただし、データベースの互換性レベルが 130 未満の場合、SQL Server 2014 (12.x)SQL Server 2014 (12.x) のしきい値が適用されます。However, if a database has a compatibility level below 130, then the SQL Server 2014 (12.x)SQL Server 2014 (12.x) threshold applies.  

重要

SQL Server 2008 R2SQL Server 2008 R2 から SQL Server 2014 (12.x)SQL Server 2014 (12.x)、または SQL Server 2016 (13.x)SQL Server 2016 (13.x) から SQL Server 2017SQL Server 2017 で、データベースの互換性レベルが 130 未満の場合、トレース フラグ 2371 を使用すると、SQL ServerSQL Server では、テーブル内の行数に基づいて調整された、より小さな値の動的な統計情報更新しきい値を使用します。Starting with SQL Server 2008 R2SQL Server 2008 R2 through SQL Server 2014 (12.x)SQL Server 2014 (12.x), or in SQL Server 2016 (13.x)SQL Server 2016 (13.x) through SQL Server 2017SQL Server 2017 under database compatibility level lower than 130, use trace flag 2371 and SQL ServerSQL Server will use a decreasing, dynamic statistics update threshold that adjusts according to the number of rows in the table.

クエリ オプティマイザーによる古い統計の確認は、クエリをコンパイルする前と、キャッシュされたクエリ プランを実行する前に行われます。The Query Optimizer checks for out-of-date statistics before compiling a query and before executing a cached query plan. クエリをコンパイルする前は、クエリ オプティマイザーで、クエリ述語内の列、テーブル、およびインデックス付きビューを使用して古くなっている可能性がある統計が判断されます。Before compiling a query, the Query Optimizer uses the columns, tables, and indexed views in the query predicate to determine which statistics might be out-of-date. キャッシュされたクエリ プランを実行する前は、 データベース エンジンDatabase Engine で、クエリ プランが最新の統計を参照しているかどうかが確認されます。Before executing a cached query plan, the データベース エンジンDatabase Engine verifies that the query plan references up-to-date statistics.

AUTO_UPDATE_STATISTICS オプションは、インデックスに対して作成された統計オブジェクト、クエリ述語内の列に対して 1 列ずつ作成された統計オブジェクト、および CREATE STATISTICS ステートメントを使用して作成された統計に適用されます。The AUTO_UPDATE_STATISTICS option applies to statistics objects created for indexes, single-columns in query predicates, and statistics created with the CREATE STATISTICS statement. また、フィルター選択された統計情報にも適用されます。This option also applies to filtered statistics.

AUTO_UPDATE_STATISTICS の制御の詳細については、「SQL Server 内の Autostat (AUTO_UPDATE_STATISTICS) の動作を制御します。」をご覧ください。For more information about controlling AUTO_UPDATE_STATISTICS, see Controlling Autostat (AUTO_UPDATE_STATISTICS) behavior in SQL Server.

AUTO_UPDATE_STATISTICS_ASYNCAUTO_UPDATE_STATISTICS_ASYNC

統計の非同期更新オプション AUTO_UPDATE_STATISTICS_ASYNC によって、クエリ オプティマイザーで統計の同期更新と非同期更新のどちらを使用するかが決まります。The asynchronous statistics update option, AUTO_UPDATE_STATISTICS_ASYNC, determines whether the Query Optimizer uses synchronous or asynchronous statistics updates. 既定では、統計の非同期更新オプションはオフであり、クエリ オプティマイザーによる統計の更新は同期更新になります。By default, the asynchronous statistics update option is OFF, and the Query Optimizer updates statistics synchronously. AUTO_UPDATE_STATISTICS_ASYNC オプションは、インデックスに対して作成された統計オブジェクト、クエリ述語内の列に対して 1 列ずつ作成された統計オブジェクト、および CREATE STATISTICS ステートメントを使用して作成された統計に適用されます。The AUTO_UPDATE_STATISTICS_ASYNC option applies to statistics objects created for indexes, single columns in query predicates, and statistics created with the CREATE STATISTICS statement.

注意

SQL Server Management StudioSQL Server Management Studio[データベースのプロパティ] ウィンドウの [オプション] ページで統計の非同期更新オプションを設定するには、[統計の自動更新][統計の非同期的自動更新] の両方のオプションを True に設定する必要があります。To set the asynchronous statistics update option in SQL Server Management StudioSQL Server Management Studio, in the Options page of the Database Properties window, both Auto Update Statistics and Auto Update Statistics Asynchronously options need to be set to True.

統計の更新には、同期更新 (既定) と非同期更新があります。Statistics updates can be either synchronous (the default) or asynchronous. 統計の同期更新では、クエリは常に最新の統計を使用してコンパイルおよび実行されます。統計が古い場合、クエリ オプティマイザーでは、統計が更新されるまでクエリのコンパイルおよび実行を待機します。With synchronous statistics updates, queries always compile and execute with up-to-date statistics; When statistics are out-of-date, the Query Optimizer waits for updated statistics before compiling and executing the query. 統計の非同期更新では、クエリは、既存の統計が古い場合でもその統計を使用してコンパイルされます。クエリのコンパイル時に古い統計が使用された場合、クエリ オプティマイザーで最適なクエリ プランが選択されない可能性があります。With asynchronous statistics updates, queries compile with existing statistics even if the existing statistics are out-of-date; The Query Optimizer could choose a suboptimal query plan if statistics are out-of-date when the query compiles. 非同期更新の完了後にコンパイルされるクエリには、更新された統計を使用できます。Queries that compile after the asynchronous updates have completed will benefit from using the updated statistics.

テーブルの切り捨てや大部分の行の一括更新を行うなど、データの分布が変わる操作を実行する場合は、同期統計を使用することを検討してください。Consider using synchronous statistics when you perform operations that change the distribution of data, such as truncating a table or performing a bulk update of a large percentage of the rows. 操作が完了した後に統計を更新していない場合、同期統計を使用すれば、変更されたデータに対するクエリを実行する前に統計が最新になります。If you do not update the statistics after completing the operation, using synchronous statistics will ensure statistics are up-to-date before executing queries on the changed data.

次のような場合は、非同期統計を使用してクエリの応答時間を予測しやすくすることを検討してください。Consider using asynchronous statistics to achieve more predictable query response times for the following scenarios:

  • アプリケーションで同じクエリ、類似のクエリ、またはキャッシュされた類似のクエリ プランを頻繁に実行する場合。Your application frequently executes the same query, similar queries, or similar cached query plans. クエリの応答時間は、統計の同期更新を使用するよりも非同期更新を使用した方が予測しやすくなります。非同期更新の場合、クエリ オプティマイザーでは、統計が最新になるまで待機せずに着信クエリを実行できるためです。Your query response times might be more predictable with asynchronous statistics updates than with synchronous statistics updates because the Query Optimizer can execute incoming queries without waiting for up-to-date statistics. これにより、一部のクエリの遅延については回避することができます。This avoids delaying some queries and not others.

  • アプリケーションで統計の更新を待機している 1 つ以上のクエリによって、クライアント要求がタイムアウトする場合。Your application has experienced client request time outs caused by one or more queries waiting for updated statistics. 場合によっては、同期統計を待機していることが原因で、厳しいタイムアウト時間が設定されたアプリケーションが失敗することがあります。In some cases, waiting for synchronous statistics could cause applications with aggressive time outs to fail.

INCREMENTAL INCREMENTAL

CREATE STATISTICS の INCREMENTAL オプションが ON の場合、作成される統計情報はパーティションごとの統計になります。When INCREMENTAL option of CREATE STATISTICS is ON, the statistics created are per partition statistics. OFF の場合、統計ツリーが削除され、 SQL ServerSQL Server によって統計が再計算されます。When OFF, the statistics tree is dropped and SQL ServerSQL Server re-computes the statistics. 既定値は OFF です。The default is OFF. この設定は、データベース レベルの INCREMENTAL プロパティをオーバーライドします。This setting overrides the database level INCREMENTAL property. 増分統計の作成の詳細については、「CREATE STATISTICS (Transact-SQL)」を参照してください。For more information about creating incremental statistics, see CREATE STATISTICS (Transact-SQL). パーティションごとの統計を自動的に作成する方法の詳細については、「[データベースのプロパティ] ([オプション] ページ)」と「ALTER DATABASE の SET オプション (Transact-SQL)」を参照してください。For more information about creating per partition statistics automatically, see Database Properties (Options Page) and ALTER DATABASE SET Options (Transact-SQL).

大きなテーブルに新しいパーティションを追加した場合、新しいパーティションが含まれるように統計を更新する必要があります。When new partitions are added to a large table, statistics should be updated to include the new partitions. ただし、テーブル全体のスキャン (FULLSCAN または SAMPLE オプション) に要する時間は非常に長くなることがあります。However the time required to scan the entire table (FULLSCAN or SAMPLE option) might be quite long. また、新しいパーティションに対する統計のみが必要となるため、テーブル全体をスキャンする必要はありません。Also, scanning the entire table isn't necessary because only the statistics on the new partitions might be needed. 増分オプションでは、パーティションごとの統計が作成され格納されるため、更新時には、新しい統計を必要とするそれらのパーティションの統計のみを更新します。The incremental option creates and stores statistics on a per partition basis, and when updated, only refreshes statistics on those partitions that need new statistics

パーティションごとの統計がサポートされていない場合、このオプションは無視され、警告が生成されます。If per partition statistics are not supported the option is ignored and a warning is generated. 次の種類の統計では、増分統計がサポートされていません。Incremental stats are not supported for following statistics types:

  • ベース テーブルにパーティションで固定されていないインデックスを使用して作成された統計。Statistics created with indexes that are not partition-aligned with the base table.
  • Always On の読み取り可能なセカンダリ データベースに対して作成された統計。Statistics created on Always On readable secondary databases.
  • 読み取り専用のデータベースに対して作成された統計。Statistics created on read-only databases.
  • フィルター選択されたインデックスに対して作成された統計。Statistics created on filtered indexes.
  • ビューに対して作成された統計。Statistics created on views.
  • 内部テーブルに対して作成された統計。Statistics created on internal tables.
  • 空間インデックスまたは XML インデックスを使用して作成された統計。Statistics created with spatial indexes or XML indexes.

適用対象: SQL Server 2014 (12.x)SQL Server 2014 (12.x) から SQL Server 2017SQL Server 2017Applies to: SQL Server 2014 (12.x)SQL Server 2014 (12.x) through SQL Server 2017SQL Server 2017.

統計を作成する場合When to create statistics

クエリ オプティマイザーによって、既に次のようにして統計が作成されています。The Query Optimizer already creates statistics in the following ways:

  1. インデックスの作成時に、クエリ オプティマイザーによってテーブルまたはビューのインデックスに対する統計が作成されます。The Query Optimizer creates statistics for indexes on tables or views when the index is created. これらの統計は、インデックスのキー列について作成されます。These statistics are created on the key columns of the index. インデックスがフィルター選択されたインデックスの場合は、フィルター選択されたインデックスに指定された行のサブセットと同じ行のサブセットについて、フィルター選択された統計が作成されます。If the index is a filtered index, the Query Optimizer creates filtered statistics on the same subset of rows specified for the filtered index. フィルター選択されたインデックスの詳細については、「フィルター選択されたインデックスの作成」および 「CREATE INDEX (Transact-SQL)」を参照してください。For more information about filtered indexes, see Create Filtered Indexes and CREATE INDEX (Transact-SQL).

  2. AUTO_CREATE_STATISTICS がオンの場合、クエリ オプティマイザーによってクエリ述語内の列に対して 1 列ずつ統計が作成されます。The Query Optimizer creates statistics for single columns in query predicates when AUTO_CREATE_STATISTICS is on.

ほとんどのクエリでは、これらの 2 つの方法で作成された統計を使用すれば、高品質のクエリ プランになります。ただし、 CREATE STATISTICS ステートメントを使用して追加の統計を作成することで、クエリ プランが向上する場合もあります。For most queries, these two methods for creating statistics ensure a high-quality query plan; in a few cases, you can improve query plans by creating additional statistics with the CREATE STATISTICS statement. これらの追加の統計では、クエリ オプティマイザーでインデックスまたは 1 列ずつの統計を作成する場合には考慮されない統計的相関関係を取り込むことができます。These additional statistics can capture statistical correlations that the Query Optimizer does not account for when it creates statistics for indexes or single columns. アプリケーションのテーブル データには、計算して統計オブジェクトに含めればクエリ オプティマイザーでクエリ プランを向上させることができる、他の統計的相関関係が含まれている場合があります。Your application might have additional statistical correlations in the table data that, if calculated into a statistics object, could enable the Query Optimizer to improve query plans. たとえば、データ行のサブセットに関するフィルター選択された統計情報や、クエリ述語列の複数列統計を使用することで、クエリ プランが向上することがあります。For example, filtered statistics on a subset of data rows or multicolumn statistics on query predicate columns might improve the query plan.

CREATE STATISTICS ステートメントを使用して統計を作成する場合、AUTO_CREATE_STATISTICS オプションをオンのままにし、クエリ述語列に対する 1 列ずつの統計がクエリ オプティマイザーによって通常どおり作成されるようにしておくことをお勧めします。When creating statistics with the CREATE STATISTICS statement, we recommend keeping the AUTO_CREATE_STATISTICS option on so that the Query Optimizer continues to routinely create single-column statistics for query predicate columns. クエリ述語の詳細については、「検索条件 (Transact-SQL)」を参照してください。 For more information about query predicates, see Search Condition (Transact-SQL).

次のいずれかに該当する場合は、CREATE STATISTICS ステートメントを使用して統計を作成することを検討してください。Consider creating statistics with the CREATE STATISTICS statement when any of the following applies:

  • データベース エンジンDatabase Engine チューニング アドバイザーで統計を作成するように提示される。The データベース エンジンDatabase Engine Tuning Advisor suggests creating statistics.
  • 相関関係にある複数の列がクエリ述語に含まれているが、それらがまだ同じインデックスに存在しない。The query predicate contains multiple correlated columns that are not already in the same index.
  • データのサブセットから選択するクエリを使用する。The query selects from a subset of data.
  • クエリに統計がない。The query has missing statistics.

相関関係にある複数の列がクエリ述語に含まれているQuery Predicate contains multiple correlated columns

列間に相関関係や依存関係がある複数の列がクエリ述語に含まれている場合、複数列の統計を使用するとクエリ プランが向上することがあります。When a query predicate contains multiple columns that have cross-column relationships and dependencies, statistics on the multiple columns might improve the query plan. 複数列の統計には、 密度と呼ばれる列間の相関関係の統計が含まれます。これは、1 列ずつの統計では使用できません。Statistics on multiple columns contain cross-column correlation statistics, called densities, that are not available in single-column statistics. 複数の列間のデータの相関関係によってクエリ結果が異なる場合、密度を使用するとカーディナリティの推定が向上します。Densities can improve cardinality estimates when query results depend on data relationships among multiple columns.

列が同じインデックスに既に存在する場合、複数列統計オブジェクトは既に存在するため、手動で作成する必要はありません。If the columns are already in the same index, the multicolumn statistics object already exists and it is not necessary to create it manually. 列が同じインデックスにまだ存在しない場合は、列のインデックスを作成するか CREATE STATISTICS ステートメントを使用することによって、複数列統計を作成できます。If the columns are not already in the same index, you can create multicolumn statistics by creating an index on the columns or by using the CREATE STATISTICS statement. メンテナンスに必要なシステム リソースは、インデックスの方が統計オブジェクトよりも多くなります。It requires more system resources to maintain an index than a statistics object. 複数列のインデックスを必要としないアプリケーションの場合は、インデックスを作成せずに統計オブジェクトを作成すると、システム リソースを節約できます。If the application does not require the multicolumn index, you can economize on system resources by creating the statistics object without creating the index.

複数列統計を作成する場合、統計オブジェクト定義内の列の順序によって、カーディナリティの推定に密度を使用した場合の効果が変わります。When creating multicolumn statistics, the order of the columns in the statistics object definition affects the effectiveness of densities for making cardinality estimates. 統計オブジェクトには、統計オブジェクト定義内のキー列の各プレフィックスの密度が格納されます。The statistics object stores densities for each prefix of key columns in the statistics object definition. 密度の詳細については、このページの密度に関するセクションを参照してください。For more information about densities, see Density section in this page.

カーディナリティの推定に効果的な密度を作成するには、クエリ述語内の列が、統計オブジェクト定義内の列のいずれかのプレフィックスに一致する必要があります。To create densities that are useful for cardinality estimates, the columns in the query predicate must match one of the prefixes of columns in the statistics object definition. たとえば、次の例では、列 LastNameMiddleName、および FirstNameに対する複数列統計オブジェクトを作成しています。For example, the following creates a multicolumn statistics object on the columns LastName, MiddleName, and FirstName.

USE AdventureWorks2012;  
GO  
IF EXISTS (SELECT name FROM sys.stats  
    WHERE name = 'LastFirst'  
    AND object_ID = OBJECT_ID ('Person.Person'))  
DROP STATISTICS Person.Person.LastFirst;  
GO  
CREATE STATISTICS LastFirst ON Person.Person (LastName, MiddleName, FirstName);  
GO  

この例では、統計オブジェクト LastFirst に、列プレフィックス ((LastName))、((LastName, MiddleName))、および ((LastName, MiddleName, FirstName)) の密度が格納されています。In this example, the statistics object LastFirst has densities for the following column prefixes: (LastName), (LastName, MiddleName), and (LastName, MiddleName, FirstName). ((LastName, FirstName)) の密度は使用できません。The density is not available for (LastName, FirstName). LastName を使用せずに FirstNameMiddleName を使用したクエリの場合は、カーディナリティの推定に密度を使用することはできません。If the query uses LastName and FirstName without using MiddleName, the density is not available for cardinality estimates.

データのサブセットから選択するクエリを使用するQuery Selects from a subset of data

クエリ オプティマイザーでは、1 列ずつおよびインデックスに対して統計を作成する際、すべての行の値に対する統計を作成します。When the Query Optimizer creates statistics for single columns and indexes, it creates the statistics for the values in all rows. 行のサブセットから選択するクエリの場合、その行のサブセットのデータ分布が一意であれば、フィルター選択された統計情報を使用することでクエリ プランを向上させることができます。When queries select from a subset of rows, and that subset of rows has a unique data distribution, filtered statistics can improve query plans. フィルター選択された統計情報は、CREATE STATISTICS ステートメントを WHERE 句と共に使用してフィルター述語の式を定義することで作成できます。You can create filtered statistics by using the CREATE STATISTICS statement with the WHERE clause to define the filter predicate expression.

たとえば、AdventureWorks2012AdventureWorks2012 を使用する場合、Production.Product テーブルの各製品は、Production.ProductCategory テーブルの次の 4 つのカテゴリのいずれかに属しています:Bikes、Components、Clothing、Accessories。For example, using AdventureWorks2012AdventureWorks2012, each product in the Production.Product table belongs to one of four categories in the Production.ProductCategory table: Bikes, Components, Clothing, and Accessories. 各カテゴリでは、重量に関するデータ分布が異なります。自転車の重量は 13.77 ~ 30.0、部品の重量は 2.12 ~ 1050.00 (一部 NULL 値)、衣類の重量はすべて NULL、付属品の重量も NULL です。Each of the categories has a different data distribution for weight: bike weights range from 13.77 to 30.0, component weights range from 2.12 to 1050.00 with some NULL values, clothing weights are all NULL, and accessory weights are also NULL.

たとえば Bikes の場合、自転車のすべての重量についてのフィルター選択された統計情報を使用すると、テーブル全体の統計情報を使用する場合や、Weight 列の統計情報が存在しない場合と比べて、より正確な統計情報がクエリ オプティマイザーに提供され、クエリ プランの品質が向上します。Using Bikes as an example, filtered statistics on all bike weights will provide more accurate statistics to the Query Optimizer and can improve the query plan quality compared with full-table statistics or nonexistent statistics on the Weight column. 自転車の重量の列は、フィルター選択された統計情報には適していますが、重量の参照が比較的少ない場合、フィルター選択されたインデックスには必ずしも適しているとは限りません。The bike weight column is a good candidate for filtered statistics but not necessarily a good candidate for a filtered index if the number of weight lookups is relatively small. フィルター選択されたインデックスを使用することで得られる参照のパフォーマンスの向上よりも、フィルター選択されたインデックスをデータベースに追加するためのメンテナンス コストとストレージ コストの増加の方が大きい場合があります。The performance gain for lookups that a filtered index provides might not outweigh the additional maintenance and storage cost for adding a filtered index to the database.

次のステートメントでは、Bikes のすべてのサブカテゴリについてのフィルター選択された統計 BikeWeights を作成します。The following statement creates the BikeWeights filtered statistics on all of the subcategories for Bikes. フィルター選択された述語式で、比較 Production.ProductSubcategoryID IN (1,2,3)を使用して自転車のすべてのサブカテゴリを列挙することで、自転車を定義しています。The filtered predicate expression defines bikes by enumerating all of the bike subcategories with the comparison Production.ProductSubcategoryID IN (1,2,3). Bikes カテゴリは Production.ProductCategory テーブルに格納されているため、述語でそのカテゴリ名を使用することはできません。フィルター式に含まれるすべての列が、同じテーブル内に存在する必要があります。The predicate cannot use the Bikes category name because it is stored in the Production.ProductCategory table, and all columns in the filter expression must be in the same table.

USE AdventureWorks2012;
GO
IF EXISTS ( SELECT name FROM sys.stats
    WHERE name = 'BikeWeights'
    AND object_ID = OBJECT_ID ('Production.Product'))
DROP STATISTICS Production.Product.BikeWeights;
GO
CREATE STATISTICS BikeWeights
    ON Production.Product (Weight)
WHERE ProductSubcategoryID IN (1,2,3);
GO

クエリ オプティマイザーでは、 BikeWeights というフィルター選択された統計情報を使用して、重量が 25を超えるすべての自転車を選択する次のクエリのクエリ プランを向上させることができます。The Query Optimizer can use the BikeWeights filtered statistics to improve the query plan for the following query that selects all of the bikes that weigh more than 25.

SELECT P.Weight AS Weight, S.Name AS BikeName  
FROM Production.Product AS P  
    JOIN Production.ProductSubcategory AS S   
    ON P.ProductSubcategoryID = S.ProductSubcategoryID  
WHERE P.ProductSubcategoryID IN (1,2,3) AND P.Weight > 25  
ORDER BY P.Weight;  
GO  

統計がないことをクエリで識別するQuery identifies missing statistics

クエリ オプティマイザーでは、エラーやその他のイベントによって統計を作成できない場合、統計を使用せずにクエリ プランを作成します。If an error or other event prevents the Query Optimizer from creating statistics, the Query Optimizer creates the query plan without using statistics. クエリ オプティマイザーでは存在しない統計をマークし、次回のクエリの実行時に再生成しようとします。The Query Optimizer marks the statistics as missing and attempts to regenerate the statistics the next time the query is executed.

統計が存在しない場合は、 SQL Server Management StudioSQL Server Management Studioを使用してクエリの実行プランをグラフィカルに表示すると、警告 (赤色のテーブル名) が表示されます。Missing statistics are indicated as warnings (table name in red text) when the execution plan of a query is graphically displayed using SQL Server Management StudioSQL Server Management Studio. また、 を使用して Missing Column Statistics SQL Server プロファイラーSQL Server Profiler イベント クラスを監視すると、統計がない場合はそのことがわかります。Additionally, monitoring the Missing Column Statistics event class by using SQL Server プロファイラーSQL Server Profiler indicates when statistics are missing. 詳細については、「Errors and Warnings イベント カテゴリ (データベース エンジン)」を参照してください。For more information, see Errors and Warnings Event Category (Database Engine).

統計がない場合は、次の手順を実行します。If statistics are missing, perform the following steps:

  • AUTO_CREATE_STATISTICSAUTO_UPDATE_STATISTICS がオンになっていることを確認します。Verify that AUTO_CREATE_STATISTICS and AUTO_UPDATE_STATISTICS are on.
  • データベースが読み取り専用ではないことを確認します。Verify that the database is not read-only. データベースが読み取り専用の場合は、新しい統計オブジェクトを保存できません。If the database is read-only, a new statistics object cannot be saved.
  • 存在しない統計を CREATE STATISTICS ステートメントを使用して作成します。Create the missing statistics by using the CREATE STATISTICS statement.

読み取り専用データベースまたは読み取り専用スナップショットに関する統計が欠落しているか、古くなっている場合、 データベース エンジンDatabase Engine は、 tempdbに一時的な統計を作成して維持します。When statistics on a read-only database or read-only snapshot are missing or stale, the データベース エンジンDatabase Engine creates and maintains temporary statistics in tempdb. データベース エンジンDatabase Engine で一時的な統計を作成する場合は、一時的な統計と永続的な統計とを区別するためのサフィックス _readonly_database_statistic が統計名に付加されます。When the データベース エンジンDatabase Engine creates temporary statistics, the statistics name is appended with the suffix _readonly_database_statistic to differentiate the temporary statistics from the permanent statistics. サフィックス _readonly_database_statistic は、 SQL ServerSQL Serverによって生成される統計用に予約されています。The suffix _readonly_database_statistic is reserved for statistics generated by SQL ServerSQL Server. 読み書き可能なデータベースでは、一時的な統計用のスクリプトを作成して再現できます。Scripts for the temporary statistics can be created and reproduced on a read-write database. スクリプトを作成する場合、Management StudioManagement Studio では、統計名のサフィックスを _readonly_database_statistic から _readonly_database_statistic_scripted に変更します。When scripted, Management StudioManagement Studio changes the suffix of the statistics name from _readonly_database_statistic to _readonly_database_statistic_scripted.

一時的な統計を作成して更新できるのは、 SQL ServerSQL Server のみです。Only SQL ServerSQL Server can create and update temporary statistics. ただし、永続的な統計の場合と同じツールを使用すると、一時的な統計を削除して、統計のプロパティを監視できます。However, you can delete temporary statistics and monitor statistics properties using the same tools that you use for permanent statistics:

  • DROP STATISTICS ステートメントを使用して一時的な統計を削除します。Delete temporary statistics using the DROP STATISTICS statement.
  • sys.stats カタログ ビューと sys.stats_columns カタログ ビューを使用して統計を監視します。Monitor statistics using the sys.stats and sys.stats_columns catalog views. sys_stats には、どの統計が一時的または永続的なものかを示すための is_temporary 列が含まれています。sys_stats includes the is_temporary column, to indicate which statistics are permanent and which are temporary.

一時的な統計は tempdbに格納されるので、 SQL ServerSQL Server サービスを再起動すると、一時的な統計はすべてなくなります。Because temporary statistics are stored in tempdb, a restart of the SQL ServerSQL Server service causes all temporary statistics to disappear.

統計を更新する場合When to update statistics

クエリ オプティマイザーでは、古くなっている可能性がある統計を判断し、それらがクエリ プランに必要な場合は更新します。The Query Optimizer determines when statistics might be out-of-date and then updates them when they are needed for a query plan. 場合によっては、 AUTO_UPDATE_STATISTICS をオンにした場合より頻繁に統計を更新することで、クエリ プランが向上し、クエリのパフォーマンスが向上することがあります。In some cases you can improve the query plan and therefore improve query performance by updating statistics more frequently than occur when AUTO_UPDATE_STATISTICS is on. 統計は、UPDATE STATISTICS ステートメントまたは sp_updatestats ストアド プロシージャを使用して更新できます。You can update statistics with the UPDATE STATISTICS statement or the stored procedure sp_updatestats.

統計を更新すると、クエリが最新の統計を使用してコンパイルされるようになります。Updating statistics ensures that queries compile with up-to-date statistics. ただし、統計の更新によりクエリが再コンパイルされます。However, updating statistics causes queries to recompile. パフォーマンスの向上を目的とする場合、クエリ プランの改善とクエリの再コンパイルに要する時間の間にはトレードオフの関係があるため、あまり頻繁に統計を更新しないようにすることをお勧めします。We recommend not updating statistics too frequently because there is a performance tradeoff between improving query plans and the time it takes to recompile queries. 実際のトレードオフはアプリケーションによって異なります。The specific tradeoffs depend on your application.

UPDATE STATISTICS または sp_updatestats を使用して統計を更新する場合、AUTO_UPDATE_STATISTICS オプションを ON に設定したままにし、通常の更新がクエリ オプティマイザーによって引き続き行われるようにしておくことをお勧めします。When updating statistics with UPDATE STATISTICS or sp_updatestats, we recommend keeping AUTO_UPDATE_STATISTICS set to ON so that the Query Optimizer continues to routinely update statistics. 列、インデックス、テーブル、またはインデックス付きビューの統計を更新する方法については、「UPDATE STATISTICS (Transact-SQL)」を参照してください。For more information about how to update statistics on a column, an index, a table, or an indexed view, see UPDATE STATISTICS (Transact-SQL). データベース内のすべてのユーザー定義および内部テーブルの統計を更新する方法については、ストアド プロシージャ sp_updatestats (Transact-SQL) の説明を参照してください。For information about how to update statistics for all user-defined and internal tables in the database, see the stored procedure sp_updatestats (Transact-SQL).

統計の最終更新日を確認するには、sys.dm_db_stats_properties または STATS_DATE 関数を使用します。To determine when statistics were last updated, use the sys.dm_db_stats_properties or STATS_DATE functions.

次のような場合は、統計を更新することを検討してください。Consider updating statistics for the following conditions:

  • クエリの実行に時間がかかる。Query execution times are slow.
  • 昇順または降順のキー列に対して挿入操作を実行する。Insert operations occur on ascending or descending key columns.
  • メンテナンス操作の実行後。After maintenance operations.

クエリの実行に時間がかかるQuery execution times are slow

クエリの応答時間が遅い場合や予測できない場合は、他のトラブルシューティング手順を実行する前に、クエリの統計が最新のものであることを確認してください。If query response times are slow or unpredictable, ensure that queries have up-to-date statistics before performing additional troubleshooting steps.

昇順または降順のキー列に対して挿入操作を実行するInsert operations occur on ascending or descending key columns

昇順または降順のキー列 (IDENTITY 列や実時間のタイムスタンプ列など) の統計では、クエリ オプティマイザーで実行されるよりも頻繁に統計の更新が必要になる場合があります。Statistics on ascending or descending key columns, such as IDENTITY or real-time timestamp columns, might require more frequent statistics updates than the Query Optimizer performs. 挿入操作によって昇順または降順の列に新しい値が追加された場合に、Insert operations append new values to ascending or descending columns. 追加された行数が少なすぎると、統計の更新が実行されないことがあります。The number of rows added might be too small to trigger a statistics update. 統計が最新ではない場合に、追加された最新の行から選択するクエリを実行すると、現在の統計にそれらの新しい値のカーディナリティの推定が含まれません。If statistics are not up-to-date and queries select from the most recently added rows, the current statistics will not have cardinality estimates for these new values. その結果、カーディナリティの推定が不正確になり、クエリのパフォーマンスが低下することがあります。This can result in inaccurate cardinality estimates and slow query performance.

たとえば、最新の販売注文日から選択するクエリで、統計が最新の販売注文日のカーディナリティの推定を含むように更新されていないと、カーディナリティの推定が不正確になります。For example, a query that selects from the most recent sales order dates will have inaccurate cardinality estimates if the statistics are not updated to include cardinality estimates for the most recent sales order dates.

メンテナンス操作の実行後After maintenance operations

テーブルの切り捨てや大部分の行の一括挿入を行うなど、データの分布が変わるメンテナンス操作を実行した後は、統計を更新することを検討してください。Consider updating statistics after performing maintenance procedures that change the distribution of data, such as truncating a table or performing a bulk insert of a large percentage of the rows. これにより、統計の自動更新を待つことによってクエリ処理で発生する以降の遅延を回避することができます。This can avoid future delays in query processing while queries wait for automatic statistics updates.

インデックスの再構築、デフラグ、再構成などの操作では、データの分布は変わりません。Operations such as rebuilding, defragmenting, or reorganizing an index do not change the distribution of data. そのため、ALTER INDEX REBUILDDBCC DBREINDEXDBCC INDEXDEFRAG、または ALTER INDEX REORGANIZE の各操作を実行した後に統計を更新する必要はありません。Therefore, you do not need to update statistics after performing ALTER INDEX REBUILD, DBCC DBREINDEX, DBCC INDEXDEFRAG, or ALTER INDEX REORGANIZE operations. ALTER INDEX REBUILD または DBCC DBREINDEX を使用してテーブルまたはビューのインデックスを再構築した場合、クエリ オプティマイザーによって統計が更新されますが、この統計の更新はインデックスを再作成する過程で実行されるものです。The Query Optimizer updates statistics when you rebuild an index on a table or view with ALTER INDEX REBUILD or DBCC DBREINDEX, however this statistics update is a byproduct of re-creating the index. DBCC INDEXDEFRAG 操作または ALTER INDEX REORGANIZE 操作の後は、クエリ オプティマイザーで統計は更新されません。The Query Optimizer does not update statistics after DBCC INDEXDEFRAG or ALTER INDEX REORGANIZE operations.

ヒント

SQL Server 2016 (13.x)SQL Server 2016 (13.x) SP1 CU4 以降では、CREATE STATISTICS (Transact-SQL) または UPDATE STATISTICS (Transact-SQL) の PERSIST_SAMPLE_PERCENT オプションを使用して、サンプリング比率が明確に指定されていない後続の統計情報更新の特定のサンプリング比率を設定し、保持します。Starting with SQL Server 2016 (13.x)SQL Server 2016 (13.x) SP1 CU4, use the PERSIST_SAMPLE_PERCENT option of CREATE STATISTICS (Transact-SQL) or UPDATE STATISTICS (Transact-SQL), to set and retain a specific sampling percentage for subsequent statistic updates that do not explicitly specify a sampling percentage.

インデックスと統計の自動管理Automatic index and statistics management

Adaptive Index Defrag のようなソリューションを活用し、1 つまたは複数のデータベースに対するインデックスの最適化と統計更新を自動管理します。Leverage solutions such as Adaptive Index Defrag to automatically manage index defragmentation and statistics updates for one or more databases. このプロシージャでは、断片化レベルやその他のパラメーターに基づいてインデックスを再構築または再構成するか、線形しきい値で統計を更新するかが自動的に選択されます。This procedure automatically chooses whether to rebuild or reorganize an index according to its fragmentation level, amongst other parameters, and update statistics with a linear threshold.

統計を効果的に使用するクエリQueries that use statistics effectively

クエリ述語にローカル変数や複雑な式が含まれている場合など、特定のクエリ実装では、最適なクエリ プランにならないことがあります。Certain query implementations, such as local variables and complex expressions in the query predicate, can lead to suboptimal query plans. クエリのデザイン ガイドラインに従って統計を効果的に使用することで、この問題を回避できる場合があります。Following query design guidelines for using statistics effectively can help to avoid this. クエリ述語の詳細については、「検索条件 (Transact-SQL)」を参照してください。 For more information about query predicates, see Search Condition (Transact-SQL).

クエリのデザイン ガイドラインを適用して統計を効果的に使用することで、クエリ述語で使用される式、変数、および関数に対する カーディナリティの推定 を向上させると、クエリ プランを向上させることができます。You can improve query plans by applying query design guidelines that use statistics effectively to improve cardinality estimates for expressions, variables, and functions used in query predicates. クエリ オプティマイザーでは、式、変数、または関数の値が不明な場合、ヒストグラムで参照する値を特定できないため、ヒストグラムから最適なカーディナリティの推定を得ることができません。When the Query Optimizer does not know the value of an expression, variable, or function, it does not know which value to lookup in the histogram and therefore cannot retrieve the best cardinality estimate from the histogram. その場合、クエリ オプティマイザーでは、ヒストグラム内のサンプリングされたすべての行の値ごとの平均行数に基づいてカーディナリティの推定を行います。Instead, the Query Optimizer bases the cardinality estimate on the average number of rows per distinct value for all of the sampled rows in the histogram. その結果、カーディナリティが適切に推定されず、クエリのパフォーマンスが低下することがあります。This leads to suboptimal cardinality estimates and can hurt query performance. ヒストグラムの詳細については、このページの「ヒストグラム」のセクション、または「sys.dm_db_stats_histogram」をご覧ください。For more information about histograms, see histogram section in this page or sys.dm_db_stats_histogram.

以下のガイドラインでは、カーディナリティの推定を向上させることによってクエリ プランを改善するためのクエリの作成方法について説明します。The following guidelines describe how to write queries to improve query plans by improving cardinality estimates.

式に対するカーディナリティの推定を向上させるImproving cardinality estimates for expressions

式に対するカーディナリティの推定を向上させるには、次のガイドラインに従います。To improve cardinality estimates for expressions, follow these guidelines:

  • 定数を含む式は可能な限り単純にします。Whenever possible, simplify expressions with constants in them. クエリ オプティマイザーでは、カーディナリティの推定を判断する前に、定数を含むすべての関数および式の評価は行われません。The Query Optimizer does not evaluate all functions and expressions containing constants prior to determining cardinality estimates. たとえば、式 ABS(-100)100 に簡略化します。For example, simplify the expression ABS(-100) to 100.

  • 式で複数の変数を使用している場合は、式の計算列を作成し、その計算列に対する統計またはインデックスを作成することを検討します。If the expression uses multiple variables, consider creating a computed column for the expression and then create statistics or an index on the computed column. たとえば、クエリ述語 WHERE PRICE + Tax > 100 のカーディナリティの推定は、式 Price + Tax に対する計算列を作成すると向上する可能性があります。For example, the query predicate WHERE PRICE + Tax > 100 might have a better cardinality estimate if you create a computed column for the expression Price + Tax.

変数および関数に対するカーディナリティの推定を向上させるImproving cardinality estimates for variables and functions

変数および関数に対するカーディナリティの推定を向上させるには、次のガイドラインに従います。To improve the cardinality estimates for variables and functions, follow these guidelines:

  • クエリ述語でローカル変数を使用している場合は、ローカル変数の代わりにパラメーターを使用してクエリを書き換えることを検討します。If the query predicate uses a local variable, consider rewriting the query to use a parameter instead of a local variable. ローカル変数の値は、クエリ オプティマイザーでのクエリ実行プランの作成時には認識されません。The value of a local variable is not known when the Query Optimizer creates the query execution plan. クエリでパラメーターを使用すると、クエリ オプティマイザーで、ストアド プロシージャに渡される最初の実際のパラメーター値に対するカーディナリティの推定が使用されます。When a query uses a parameter, the Query Optimizer uses the cardinality estimate for the first actual parameter value that is passed to the stored procedure.

  • 複数ステートメントのテーブル値関数 (mstvf) の結果を格納する場合は、標準のテーブルか一時テーブルを使用することを検討します。Consider using a standard table or temporary table to hold the results of multi-statement table-valued functions (mstvf). クエリ オプティマイザーでは、複数ステートメントのテーブル値関数の統計は作成されません。The Query Optimizer does not create statistics for multi-statement table-valued functions. この方法を使用すると、クエリ オプティマイザーでテーブル列の統計を作成できるため、それを使用することでクエリ プランを向上させることができます。With this approach the Query Optimizer can create statistics on the table columns and use them to create a better query plan.

  • テーブル変数の代わりに標準のテーブルか一時テーブルを使用することを検討します。Consider using a standard table or temporary table as a replacement for table variables. クエリ オプティマイザーでは、テーブル変数の統計は作成されません。The Query Optimizer does not create statistics for table variables. この方法を使用すると、クエリ オプティマイザーでテーブル列の統計を作成できるため、それを使用することでクエリ プランを向上させることができます。With this approach the Query Optimizer can create statistics on the table columns and use them to create a better query plan. 一時テーブルとテーブル変数のどちらを使用するかの判断には、トレードオフの関係があります。ストアド プロシージャでテーブル変数を使用すると、ストアド プロシージャの再コンパイルの回数が、一時テーブルを使用した場合よりも少なくなります。There are tradeoffs in determining whether to use a temporary table or a table variable; Table variables used in stored procedures cause fewer recompilations of the stored procedure than temporary tables. アプリケーションによっては、テーブル変数の代わりに一時テーブルを使用しても、パフォーマンスが向上しない場合もあります。Depending on the application, using a temporary table instead of a table variable might not improve performance.

  • 渡されたパラメーターを使用するクエリがストアド プロシージャに含まれている場合は、パラメーター値がクエリで使用される前にストアド プロシージャ内で変更されないようにします。If a stored procedure contains a query that uses a passed-in parameter, avoid changing the parameter value within the stored procedure before using it in the query. クエリに対するカーディナリティの推定は、更新された値ではなく渡されたパラメーターの値に基づいて行われます。The cardinality estimates for the query are based on the passed-in parameter value and not the updated value. パラメーター値が変更されないようにするには、2 つのストアド プロシージャを使用するようにクエリを書き換えます。To avoid changing the parameter value, you can rewrite the query to use two stored procedures.

    たとえば、次のストアド プロシージャ Sales.GetRecentSales では、@date が NULL の場合にパラメーター @date の値を変更します。For example, the following stored procedure Sales.GetRecentSales changes the value of the parameter @date when @date is NULL.

    USE AdventureWorks2012;  
    GO  
    IF OBJECT_ID ( 'Sales.GetRecentSales', 'P') IS NOT NULL  
        DROP PROCEDURE Sales.GetRecentSales;  
    GO  
    CREATE PROCEDURE Sales.GetRecentSales (@date datetime)  
    AS BEGIN  
        IF @date IS NULL  
            SET @date = DATEADD(MONTH, -3, (SELECT MAX(ORDERDATE) FROM Sales.SalesOrderHeader))  
        SELECT * FROM Sales.SalesOrderHeader h, Sales.SalesOrderDetail d  
        WHERE h.SalesOrderID = d.SalesOrderID  
        AND h.OrderDate > @date  
    END  
    GO  
    

    ストアド プロシージャ Sales.GetRecentSales の最初の呼び出しで @date パラメーターに NULL が渡された場合、クエリ オプティマイザーでは、クエリ述語が @date = NULL で呼び出されていなくても、 @date = NULLに対するカーディナリティの推定を使用してストアド プロシージャをコンパイルします。If the first call to the stored procedure Sales.GetRecentSales passes a NULL for the @date parameter, the Query Optimizer will compile the stored procedure with the cardinality estimate for @date = NULL even though the query predicate is not called with @date = NULL. このカーディナリティの推定は、実際のクエリ結果の行数と大きく異なる場合があります。This cardinality estimate might be significantly different than the number of rows in the actual query result. そのため、クエリ オプティマイザーにより、最適なクエリ プランが選択されないことがあります。As a result, the Query Optimizer might choose a suboptimal query plan. この問題を回避するには、ストアド プロシージャを次のように 2 つのプロシージャに書き換えます。To help avoid this, you can rewrite the stored procedure into two procedures as follows:

    USE AdventureWorks2012;  
    GO  
    IF OBJECT_ID ( 'Sales.GetNullRecentSales', 'P') IS NOT NULL  
        DROP PROCEDURE Sales.GetNullRecentSales;  
    GO  
    CREATE PROCEDURE Sales.GetNullRecentSales (@date datetime)  
    AS BEGIN  
        IF @date is NULL  
            SET @date = DATEADD(MONTH, -3, (SELECT MAX(ORDERDATE) FROM Sales.SalesOrderHeader))  
        EXEC Sales.GetNonNullRecentSales @date;  
    END  
    GO  
    IF OBJECT_ID ( 'Sales.GetNonNullRecentSales', 'P') IS NOT NULL  
        DROP PROCEDURE Sales.GetNonNullRecentSales;  
    GO  
    CREATE PROCEDURE Sales.GetNonNullRecentSales (@date datetime)  
    AS BEGIN  
        SELECT * FROM Sales.SalesOrderHeader h, Sales.SalesOrderDetail d  
        WHERE h.SalesOrderID = d.SalesOrderID  
        AND h.OrderDate > @date  
    END  
    GO  
    

クエリ ヒントを使用してカーディナリティの推定を向上させるImproving cardinality estimates with query hints

ローカル変数に対するカーディナリティの推定を向上させるには、RECOMPILE を指定して OPTIMIZE FOR <value> または OPTIMIZE FOR UNKNOWN クエリ ヒントを使用します。To improve cardinality estimates for local variables, you can use the OPTIMIZE FOR <value> or OPTIMIZE FOR UNKNOWN query hints with RECOMPILE. 詳細については、「クエリ ヒント (Transact-SQL)」を参照してください。For more information, see Query Hints (Transact-SQL).

アプリケーションによっては、クエリを実行するたびに再コンパイルすると時間がかかりすぎる場合がありますが、For some applications, recompiling the query each time it executes might take too much time. OPTIMIZE FOR クエリ ヒントは RECOMPILE オプションを使用しなくても役立つことがあります。The OPTIMIZE FOR query hint can help even if you don't use the RECOMPILE option. たとえば、ストアド プロシージャ Sales.GetRecentSales に OPTIMIZE FOR オプションを追加して、特定の日付を指定することができます。For example, you could add an OPTIMIZE FOR option to the stored procedure Sales.GetRecentSales to specify a specific date. Sales.GetRecentSales プロシージャに OPTIMIZE FOR オプションを追加する例を次に示します。The following example adds the OPTIMIZE FOR option to the Sales.GetRecentSales procedure.

USE AdventureWorks2012;  
GO  
IF OBJECT_ID ( 'Sales.GetRecentSales', 'P') IS NOT NULL  
    DROP PROCEDURE Sales.GetRecentSales;  
GO  
CREATE PROCEDURE Sales.GetRecentSales (@date datetime)  
AS BEGIN  
    IF @date is NULL  
        SET @date = DATEADD(MONTH, -3, (SELECT MAX(ORDERDATE) FROM Sales.SalesOrderHeader))  
    SELECT * FROM Sales.SalesOrderHeader h, Sales.SalesOrderDetail d  
    WHERE h.SalesOrderID = d.SalesOrderID  
    AND h.OrderDate > @date  
    OPTION ( OPTIMIZE FOR ( @date = '2004-05-01 00:00:00.000'))  
END;  
GO  

プラン ガイドを使用してカーディナリティの推定を向上させるImproving cardinality estimates with Plan Guides

アプリケーションによっては、クエリを変更できない場合や、RECOMPILE クエリ ヒントを使用すると再コンパイルが多くなりすぎる場合など、クエリのデザイン ガイドラインを適用できないことがあります。For some applications, query design guidelines might not apply because you cannot change the query or using the RECOMPILE query hint might be cause too many recompiles. プラン ガイドを使用すると、アプリケーション ベンダーによるアプリケーションの違いを確認しながら、その他のヒント (USE PLAN など) を指定してクエリの動作を制御することができます。You can use plan guides to specify other hints, such as USE PLAN, to control the behavior of the query while investigating application changes with the application vendor. プラン ガイドの詳細については、「 Plan Guides」を参照してください。For more information about plan guides, see Plan Guides.

参照See Also

CREATE STATISTICS (Transact-SQL) CREATE STATISTICS (Transact-SQL)
UPDATE STATISTICS (Transact-SQL) UPDATE STATISTICS (Transact-SQL)
sp_updatestats (Transact-SQL) sp_updatestats (Transact-SQL)
DBCC SHOW_STATISTICS (Transact-SQL) DBCC SHOW_STATISTICS (Transact-SQL)
ALTER DATABASE SET オプション (Transact-SQL) ALTER DATABASE SET Options (Transact-SQL)
DROP STATISTICS (Transact-SQL) DROP STATISTICS (Transact-SQL)
CREATE INDEX (Transact-SQL) CREATE INDEX (Transact-SQL)
ALTER INDEX (Transact-SQL) ALTER INDEX (Transact-SQL)
フィルター選択されたインデックスの作成 Create Filtered Indexes
SQL Server で Autostat (AUTO_UPDATE_STATISTICS) 動作を制御する Controlling Autostat (AUTO_UPDATE_STATISTICS) behavior in SQL Server
STATS_DATE (Transact-SQL) STATS_DATE (Transact-SQL)
sys.dm_db_stats_properties (Transact-SQL) sys.dm_db_stats_properties (Transact-SQL)
sys.dm_db_stats_histogram (Transact-SQL)sys.dm_db_stats_histogram (Transact-SQL)
sys.statssys.stats
sys.stats_columns (Transact-SQL) sys.stats_columns (Transact-SQL)
Adaptive Index DefragAdaptive Index Defrag