sql >> データベース >  >> RDS >> Sqlserver

SQLServer2014インクリメンタル統計

    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

    最初のDBCC結果

    したがって、統計オブジェクトにはすでに最大のステップがあります。新しいパーティションにデータを追加するとどうなりますか?パーティション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

    増分更新後のDBCCの結果

    何らかの理由で増分統計を無効にする場合は、次のステートメントを使用して元の動作に戻すことができます(または、オプションで統計オブジェクトを削除して新しいオブジェクトを作成することもできます)。

    UPDATE STATISTICS dbo.TransactionHistory(incrstats) 
      WITH FULLSCAN, INCREMENTAL = OFF;

    前に示したようにパーティションを更新しようとして増分統計を無効にした後、次のエラーメッセージが返されます。

    Msg 9111、レベル16、状態1
    UPDATE STATISTICS ON PARTITIONS構文は、非増分統計ではサポートされていません。

    最後に、必要に応じて、データベースレベルで自動統計の増分統計を有効にすることもできます。これには、 INCREMENTAL =ONが必要です。 ALTER DATABASEの句 ステートメントであり、明らかに AUTO_CREATE_STATISTICSも必要です ONに設定 。


    1. 5データベース監視を改善するためのSQL構文とクエリの原則

    2. INOUTパラメータを使用したOracleの例のストアドプロシージャ

    3. ダイレクトNFSでのORA-4031エラー

    4. MariaDBでEXTRACTVALUE()がどのように機能するか