Benjamin Nevarezは、カリフォルニア州ロサンゼルスを拠点とする独立コンサルタントであり、SQLServerクエリのチューニングと最適化を専門としています。彼は「SQLServer2014クエリの調整と最適化」および「SQLServerクエリオプティマイザーの内部」の著者であり、「SQLServer2012の内部」の共著者です。リレーショナルデータベースで20年以上の経験を持つベンジャミンは、PASSサミット、SQL Server接続、SQLBitsなどの多くのSQLServer会議でも講演を行ってきました。ベンジャミンのブログはhttp://www.benjaminnevarez.comにあります。また、メールでbenjaminnevarez dot comに、ツイッターで@BenjaminNevarezにアクセスすることもできます。
SQL Serverの大きなテーブルの統計を更新する際の主な問題は、たとえば WITH FULLSCAN
を使用する場合、テーブル全体を常にスキャンする必要があることです。 最近のデータのみが変更された場合でも、オプション。これは、パーティショニングを使用する場合にも当てはまります。統計が最後に更新されてから最新のパーティションのみが変更された場合でも、変更されなかったすべてのパーティションを含むテーブル全体をスキャンするには、統計を再度更新する必要があります。 SQL Server 2014の新機能である増分統計は、この問題に役立ちます。
インクリメンタル統計を使用すると、必要な1つまたは複数のパーティションのみを更新でき、これらのパーティションの情報が既存の情報とマージされて、最終的な統計オブジェクトが作成されます。増分統計のもう1つの利点は、統計の自動更新をトリガーするために必要なデータ変更の割合がパーティションレベルで機能するようになったことです。つまり、基本的に、パーティションごとに変更された行(先頭の統計列の変更)の20%のみが必要です。残念ながら、このバージョンのSQL Serverでは、統計オブジェクト全体のヒストグラムは200ステップに制限されています。
パーティションレベルで統計を更新して、少なくともSQL Server2014CTP2の時点での動作を調べる方法の例を見てみましょう。まず、AdventureWorks2012データベースを使用してパーティションテーブルを作成する必要があります。
CREATE PARTITION FUNCTION TransactionRangePF1 (DATETIME) AS RANGE RIGHT FOR VALUES ( '20071001', '20071101', '20071201', '20080101', '20080201', '20080301', '20080401', '20080501', '20080601', '20080701', '20080801' ); GO CREATE PARTITION SCHEME TransactionsPS1 AS PARTITION TransactionRangePF1 TO ( [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY] ); GO CREATE TABLE dbo.TransactionHistory ( TransactionID INT NOT NULL, -- not bothering with IDENTITY here ProductID INT NOT NULL, ReferenceOrderID INT NOT NULL, ReferenceOrderLineID INT NOT NULL DEFAULT (0), TransactionDate DATETIME NOT NULL DEFAULT (GETDATE()), TransactionType NCHAR(1) NOT NULL, Quantity INT NOT NULL, ActualCost MONEY NOT NULL, ModifiedDate DATETIME NOT NULL DEFAULT (GETDATE()), CONSTRAINT CK_TransactionType CHECK (UPPER(TransactionType) IN (N'W', N'S', N'P')) ) ON TransactionsPS1 (TransactionDate); GO
注:パーティション分割と CREATE PARTITION FUNCTION / SCHEME
の詳細については ステートメントは、BooksOnlineのパーティション化されたテーブルとインデックスを参照してください。
現在、12個のパーティションにデータを入力するためのデータがあります。最初に11個だけを入力することから始めましょう。
INSERT INTO dbo.TransactionHistory SELECT * FROM Production.TransactionHistory WHERE TransactionDate < '2008-08-01';
必要に応じて、次のステートメントを使用してパーティションの内容を調べることができます。
SELECT * FROM sys.partitions WHERE object_id = OBJECT_ID('dbo.TransactionHistory');
CREATE STATISTICS
を使用して増分統計オブジェクトを作成しましょう 新しいINCREMENTAL
を含むステートメント 句をON
に設定 (オフコード> デフォルトです):
CREATE STATISTICS incrstats ON dbo.TransactionHistory(TransactionDate) WITH FULLSCAN, INCREMENTAL = ON;
新しいSTATISTICS_INCREMENTAL
を使用して、インデックスの作成中に増分統計を作成することもできます。 CREATE INDEX
の句 ステートメント。
DBCC
を使用して、作成された統計オブジェクトを検査できます。 :
DBCC SHOW_STATISTICS('dbo.TransactionHistory', incrstats);
特に、ヒストグラムには200のステップがあることに気付くでしょう(ここに示されているのは最後の3つだけです):
RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | |
198 | 2008-07-25 00:00:00.000 | 187 | 100 | 2 |
199 | 2008-07-27 00:00:00.000 | 103 | 101 | 1 |
200 | 2008-07-31 00:00:00.000 | 281 | 131 | 3 |
したがって、統計オブジェクトにはすでに最大のステップがあります。新しいパーティションにデータを追加するとどうなりますか?パーティション12にデータを追加しましょう:
INSERT INTO dbo.TransactionHistory SELECT * FROM Production.TransactionHistory WHERE TransactionDate >= '2008-08-01';
ここで、次のステートメントを使用して統計オブジェクトを更新します。
UPDATE STATISTICS dbo.TransactionHistory(incrstats) WITH RESAMPLE ON PARTITIONS(12);
パーティションを指定する新しい構文に注意してください。ここでは、コンマで区切って複数のパーティションを指定できます。 UPDATE STATISTICS
ステートメントは、指定されたパーティションを読み取り、その結果を既存の統計オブジェクトとマージして、グローバル統計を作成します。 RESAMPLE
に注意してください 句;これが必要なのは、パーティション統計がグローバル統計を構築するためにマージされるのと同じサンプルレートを持つ必要があるためです。指定されたパーティションのみがスキャンされましたが、SQLServerがヒストグラムを再配置したことがわかります。最後の3つの手順で、追加されたパーティションのデータが表示されます。他の小さな違いについては、元のヒストグラムと新しいヒストグラムを比較することもできます。
RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | |
197 | 2008-07-31 00:00:00.000 | 150 | 131 | 2 |
198 | 2008-08-12 00:00:00.000 | 300 | 36 | 9 |
199 | 2008-08-22 00:00:00.000 | 229 | 43 | 7 |
200 | 2008-09-03 00:00:00.000 | 363 | 37 | 11 |
何らかの理由で増分統計を無効にする場合は、次のステートメントを使用して元の動作に戻すことができます(または、オプションで統計オブジェクトを削除して新しいオブジェクトを作成することもできます)。
UPDATE STATISTICS dbo.TransactionHistory(incrstats) WITH FULLSCAN, INCREMENTAL = OFF;
前に示したようにパーティションを更新しようとして増分統計を無効にした後、次のエラーメッセージが返されます。
Msg 9111、レベル16、状態1UPDATE STATISTICS ON PARTITIONS構文は、非増分統計ではサポートされていません。
最後に、必要に応じて、データベースレベルで自動統計の増分統計を有効にすることもできます。これには、 INCREMENTAL =ON
が必要です。 ALTER DATABASE
の句 ステートメントであり、明らかに AUTO_CREATE_STATISTICS
も必要です ON
に設定 。