web-dev-qa-db-ja.com

パーティションテーブル上の複合クラスター化主キーの列の順序?

次の表があります。

create table T (K1 date, K2 int references S(Id), ....) on partitionScheme(K1)

テーブルはK1によってパーティション化されます(K1は選択性が低いです。データはK1の順に追加されます)。次の主キー(列の順序が異なる)のどれが優先されますか?

alter table T add primary key clustered (K1, K2)
alter table T add primary key clustered (K2, K1)

または、PKを非クラスター化して別のクラスター化インデックスを作成する必要がありますか?

クエリの多くは次のようになります。

select ....
from T join S on S.Id = T.K2
where ....
6
u23432534

次の主キー(列の順序が異なる)のどれが優先されますか?

すべてのインデックス作成の決定と同様に、多くはテーブルがどのようにクエリされるかに依存します。

すべてのパーティションインデックス(SQL Server 2008以降の場合)には、各パーティションインデックスの非表示の主要なキー列としてパーティションID(パーティションのキー値ではない)があるため、効果的な競合定義は:

PartitionID、K1、K2 
 vs。
 PartitionID、K2、K1

これは、予想通り、さまざまなタイプのクエリに対する各インデックスのユーティリティに影響します。主な追加の考慮事項は、PartitionID列の不等式シークやパーティションの削除操作に関係なく、最初の実キー(K1またはK2)での不等式シークが引き続きサポートされることです。

たとえば、(K1、K2)インデックス指定は、パーティションの範囲とK1値の範囲を同時にシークできます。

SELECT T1.* 
FROM dbo.T1 AS T1
WHERE 1 = 1
AND T1.K1 >= CONVERT(date, '20080711', 112)
AND T1.K1 <= CONVERT(date, '20100711', 112);

Multi-level inequality seek

クラスタ化インデックスキーとして(K2、K1)を含むテーブルで同じクエリを実行すると、パーティションの範囲を見つけることができますが、各条件を満たすパーティションを完全にスキャンして行を見つける必要があります。 K1述語と正確に一致します。明確にするために、K1値のテストは、シーク操作としてではなく、残余述語として適用されます。

これは、showplanのクラスター化インデックススキャンとして表示され、パーティションを除外するシークと、K1値の残りの述語が含まれます。

Partition elimination scan with residual predicate

dateデータ型を区分化キーとして使用する場合の微妙な点は、明示的なdate型をパーティションの削除が確実に行われることを期待する場合のクエリ。 datetimeなどの他のタイプの使用は(偶然に)簡単に実行できますが、論理的に期待される場所での除去が妨げられることがよくあります。

たとえば、次のクエリはすべてのパーティションにアクセスします。

DECLARE @dt datetime = '20080711';

SELECT * 
FROM dbo.T1 AS T1
WHERE T1.K1 = @dt;

これに対して、このクエリは単一のパーティションのみを処理します。

DECLARE @dt date = '20080711';

SELECT * 
FROM dbo.T1 AS T1
WHERE T1.K1 = @dt;

両方のクエリは、グラフィカルなプラン表示(クラスター化インデックスシーク)では表面的には同一に見えます。オペレーターのプロパティーを詳細にチェックして、静的または動的パーティション除去が適用されているかどうかを確認する必要があります。

質問で指定された結合クエリの例:両方のインデックス付け戦略にはK2列が含まれていますが、通常、どちらも並べ替えなしでK2順序で行を提供できません。結果として、どちらのインデックスもハッシュ結合またはネストされたループ結合に同等に適していますが、どちらもK2でのマージ結合に必要な入力順序を提供できません。

これは(K2、K1)インデックスでは直感に反するように見えるかもしれませんが、先頭のPartitionIDキーを覚えておいてください。各パーティションには(K2、K1)の順序で行があります。クエリでパーティションを1つだけ指定しない限り、K2の順序で行を返すために並べ替えが必要になります。 (K1、K2)インデックスは、単一のパーティションおよびK1の単一の指定された値に対して、K2の順序でのみ行を返すことができます。

提案されたクラスター化された主キー(K1、K2)は、追加データが挿入操作中にクラスター化キーによって実際にソートされる場合、ベーステーブルのページ分割を最小限に抑えるという潜在的な利点があります。 (K1、K2)インデックスの場合、これは(PartitionID、K1、K2)でソートされた行を意味します。 (K2、K1)の場合、(PartitionID、K2、K1)になります。

関連資料: パーティションテーブルとインデックスのクエリ処理の機能強化

7
Paul White 9

主キーをクラスター化しているので、これを見ると インデックスとパーティションの整列に関するTechnetの記事 クラスター化インデックスセクションで、クラスター化インデックスにパーティション化列を含めないと、あなたのために行われます。どちらのオプションにもパーティション分割列が含まれているため、これは問題ではありませんが、おそらく留意する必要があります。

クラスター化されたインデックスにパーティション列が含まれている限り(それを整列させている限り)、私が読んだことは何も言われていません。個人的には、おそらく分割された列を最初に置くでしょう。私の考えでは、SQLがインデックス内の他の列を参照する前に、どのパーティションを参照するかを決定できるように思えます。

与えられた情報に基づいて、この場合、PKとCIXを個別に用意する必要はありません。もちろん、これはK1、K2の組み合わせが一意であることを前提としています。

5
Kenneth Fisher