web-dev-qa-db-ja.com

オプティマイザにこのパーティションビュー内の無関係なテーブルを強制的に削除させることは可能ですか?

私は大きなテーブルに対してさまざまなアーキテクチャをテストしていますが、私が見た提案の1つは、分割されたビューを使用することです。これにより、大きなテーブルが一連の小さな「分割された」テーブルに分割されます。

12 、、 4

このアプローチをテストしたところ、あまり意味のないことがわかりました。ファクトビューの「パーティション分割列」でフィルタリングすると、オプティマイザは関連するテーブルのみを検索します。さらに、ディメンションテーブルのその列でフィルター処理すると、オプティマイザーは不要なテーブルを排除します。

ただし、ディメンションの他のいくつかの側面でフィルタリングすると、オプティマイザは各ベーステーブルのPK/CIを検索します。

問題のクエリは次のとおりです。

select 
    od.[Year], 
    AvgValue = avg(ObservationValue)
from dbo.v_Observation o 
join dbo.ObservationDates od
    on o.ObservationDateKey = od.DateKey
where o.ObservationDateKey >= 20000101
    and o.ObservationDateKey <= 20051231
group by od.[Year];

select 
    od.[Year], 
    AvgValue = avg(ObservationValue)
from dbo.v_Observation o 
join dbo.ObservationDates od
    on o.ObservationDateKey = od.DateKey
where od.DateKey >= 20000101
    and od.DateKey <= 20051231
group by od.[Year];

select 
    od.[Year], 
    AvgValue = avg(ObservationValue)
from dbo.v_Observation o 
join dbo.ObservationDates od
    on o.ObservationDateKey = od.DateKey
where od.[Year] >= 2000 and od.[Year] < 2006
group by od.[Year];

fact filter on key

dim filter on key

dim filter on aspect

リンクはこちら SQL Sentry Plan Explorerセッションへ。

大きなテーブルを実際にパーティション分割して、同様の方法で応答してパーティションの削除が行われるかどうかを確認しています。

ディメンションの側面でフィルターをかける(単純な)クエリのパーティションを削除します。

それまでの間、データベースの統計のみのコピーは次のとおりです。

https://Gist.github.com/swasheck/9a22bf8a580995d3b2aa

"古い"カーディナリティエスティメータはより安価なプランを取得しますが、これは、(不要な)インデックスシークごとにカーディナリティの見積もりが低いためです。

ディメンションの別の側面でフィルタリングするときにオプティマイザーがキー列を使用して、無関係なテーブルのシークを排除できる方法があるかどうか知りたいのですが。

SQL Serverのバージョン:

Microsoft SQL Server 2014 - 12.0.2000.8 (X64) 
    Feb 20 2014 20:04:26 
    Copyright (c) Microsoft Corporation
    Developer Edition (64-bit) on Windows NT 6.3 <X64> (Build 9600: ) (Hypervisor)
22
swasheck

トレースフラグ4199を有効にします。

私はまた発行しなければなりませんでした:

UPDATE STATISTICS dbo.ObservationDates 
WITH ROWCOUNT = 73049;

以下に示す計画を取得します。このテーブルの統計がアップロードにありませんでした。 73,049の数値は、プランエクスプローラーの添付ファイルにあるテーブルカーディナリティの情報に基づいています。 SQL Server 2014 SP1 CU4(ビルド12.0.4436)を使用しました。2つの論理プロセッサ、最大メモリは2048 MBに設定され、4199以外のトレースフラグはありません。

次に、動的パーティションの削除を特徴とする実行プランを取得します。

select 
    od.[Year], 
    AvgValue = avg(ObservationValue)
from dbo.v_Observation o 
join dbo.ObservationDates od
    on o.ObservationDateKey = od.DateKey
where 
    od.[Year] >= 2000 and od.[Year] < 2006
group by 
    od.[Year]
option (querytraceon 4199);

フラグメントの計画:

Plan fragment

これは悪く見えるかもしれませんが、フィルターはすべてstart-upフィルターです。述語の例は次のとおりです。

Filter properties

ループの反復ごとに、起動述語がテストされ、それがtrueを返した場合のみ、その下のクラスター化インデックスシークが実行されます。したがって、動的パーティションの除去。

これはおそらく、特に計画が並列である場合、静的除去と比べてかなりほど効率的ではありません。

同じプランを取得するには、ビューでMAXDOP 1FAST 1FORCESEEKなどのヒントを試す必要がある場合があります。パーティション化されたビュー(パーティション化されたテーブルなど)を使用したオプティマイザのコスト選択は注意が必要です。

重要なのは、パーティションビューで動的パーティションを削除するための起動フィルターを備えたプランが必要なことです。


USE PLANヒントが埋め込まれたクエリ:(Gist.github.com経由):

10
Paul White 9

私の観察では、パーティションビューで「テーブルの削除」を行うには、クエリでパーティション列の値(または値の範囲)を明示的に指定する必要があるということが常にありました。これは、SQL Server 2000からSQL Server 2014までの運用でパーティションビューを使用した経験に基づいています。

SQL Serverには、ループの外側の行の値に基づいて、エンジンがループの内側の適切なテーブルに直接シークを動的に向けることができるループ結合演算子の概念はありません。ただし、 Paulの回答で説明 のように、ループの内側にある無関係なテーブルを一定の時間で動的にスキップするために、スタートアップフィルターを使用する計画の可能性があります(実際の対数とは対照的)シークを実行します)。

ただし、パーティション化されたテーブルでは、このタイプのシーク(特定のパーティションへの)がサポートされています。

分割ビューの使用に固定されている場合、次のような別のオプションは、クエリを複数のクエリに分割することです。

-- Gather than the min/max values for the partition column
DECLARE @minDateKey INT,
        @maxDateKey INT
SELECT @minDateKey = MIN(DateKey),
        @maxDateKey = MAX(DateKey)
FROM dbo.ObservationDates od
WHERE od.[Year] >= 2000 and od.[Year] < 2006

-- Since I have a stats-only copy of the database, simulate having run the query above
-- (You can comment this out since you have the actual data.)
SELECT @minDateKey = 20000101, @maxDateKey = 20051231

-- Adjust the query to use the min/max values of the partition column
-- rather than filtering on a different column in the dimension table
select 
    od.[Year], 
    AvgValue = avg(ObservationValue)
from dbo.v_Observation o 
join dbo.ObservationDates od
    on o.ObservationDateKey = od.DateKey
WHERE od.DateKey >= @minDateKey AND od.DateKey <= @maxDateKey
group by od.[Year]
-- Must use OPTION RECOMPILE; otherwise the plan will touch all tables because it
-- must do so in order to be valid for all values of the parameters!
OPTION (RECOMPILE)

これにより、次の計画が生成されます。ディメンションテーブルにヒットする追加のクエリがありますが、(おそらくはるかに大きい)ファクトテーブルに対するクエリが最適化されます。

enter image description here

6
Geoff Patterson