web-dev-qa-db-ja.com

sys.dm_db_stats_properties DMVのパフォーマンスの低下を改善する

COLUMNSTORE圧縮(21または30 COLUMNS)と2500パーティション(日付順)のワイドテーブルを持つデータベースがあります。このデータベースには約4000の統計オブジェクトがあり、そのほとんどはパーティションテーブルのINCREMENTAL列統計です。

これらのデータベースでsys.dm_db_stats_propertiesを実行すると、このテーブル関数のパフォーマンスが非常に低下します。 ROWごと、つまりこのテーブル関数の「実行」ごとに約1秒を見ています。

これは、1605の統計とテーブルの組み合わせに対してこのテーブル関数を実行するために使用されるCROSS APPLYsyntaxを使用した単純なクエリによって生成されるクエリプランの例です。 Query Plan

ここでは、それほど役立つことは何もありません。DMVのパフォーマンスは明らかに劣っています。

私の現在の理論では、データベース内の統計オブジェクトの性質により、OPENROWSET内部テーブルに対するクエリは最適化されていません(おそらくTOP 1)。これがスローダウンの原因です。

CREATE FUNCTION sys.dm_db_stats_properties (@object_id int, @stats_id int)
RETURNS TABLE
AS
RETURN SELECT TOP 1 -- The first row in the TVF will be the root; avoid scanning entire TVF to find any additional rows.
    object_id, -- Columns now explicit since underlying tvf has additional columns we don't want to expose for backwards compat
    stats_id,
    last_updated,
    rows,
    rows_sampled,
    steps,
    unfiltered_rows,
    modification_counter,
    persisted_sample_percent
FROM OPENROWSET(TABLE DM_DB_STATS_PROPERTIES, @object_id, @stats_id)

ただし、sys.dm_db_stats_propertiesはDMVであるため不変であるため、内部テーブルなどのクエリ方法を変更することはできません。

ここでの目的は、rows, rows_sampled, unfiltered_rows, modification_counter, last_updatedから取得した列sys.dm_db_stats_propertiesの値を、データベースごとに3時間もかからない方法で取得することです。情報のソースがそれほど正確でない限り、別のDMVを使用するかどうかは問題ではありません。

すべてのシステムテーブルを再編成して、ALTER INDEX ALL ON [Database].sys.[table to reorganize] REORGANIZEなどのステートメントに影響があるかどうかを確認しました。ただし、パフォーマンスの向上は観察されませんでした。

次のバージョンのSQLサーバーを実行しています:Microsoft SQL Server 2017(RTM-CU18)(KB4527377)-14.0.3257.3(X64)on Windows Server2016。互換性レベルは140です。

8
duhamp

modification_counter からDBCC SHOW_STATISTICS以外のすべてを取得できます

DBCC SHOW_STATISTICS ( table_or_indexed_view_name , target )
WITH STAT_HEADER;

次のようなものを使用して、その出力を一時テーブルに取り込む必要があります。

CREATE TABLE #StatHeader
(
    [Name] sysname NULL,
    Updated datetime NULL,
    [Rows] bigint NULL,
    [Rows Sampled] bigint NULL,
    Steps integer NULL,
    Density float NULL,
    [Average key length] integer NULL,
    [String Index] varchar(3) NULL,
    [Filter Expression] nvarchar(max) NULL,
    [Unfiltered Rows] bigint NULL,
    [Persisted Sample Percent] integer NULL
);

INSERT #StatHeader
EXECUTE('DBCC SHOW_STATISTICS (table, stat) WITH STAT_HEADER;');

sys.sysindexesrowmodctrが代替変更カウンターを提供します。

これは回避策であり、新しいDMVが提供される前に実行していたことです。これは理想的ではなく、予想外に遅いパフォーマンスをマイクロソフトに報告する必要があります。

7
Paul White 9