バックグラウンド
私はアプリケーションを、0.5 億から 13 億のレコードを保持する単一のイベント テーブルを持つスキーマから、それぞれがその数のレコードの一部を保持する 30 から 180 の同一の基になるテーブルを持つパーティション分割されたビューに移行しています。その多くのレコードの管理とクエリ。すべてのユーザーがSQL Server 2012のAwesome Editionにアクセスできるわけではないため、テーブル パーティション分割の代わりにパーティション ビューを使用しています。
分割関数は、イベントの日のデカルト積とイベントの 1 つの属性に基づいています。つまり、属性「foo」を持つ 2015 年 6 月 1 日のすべてのイベントは「Event20150601_foo」のようなテーブルに入り、属性「bar」を持つすべてのイベントは「Event20150601_bar」に入り、翌日のイベントは「Event20150602_foo」に入り、 「Event20150602_bar」など。通常、2 ~ 3 個の属性値と 15 ~ 60 日間のイベントがあり、これは通常、30 ~ 180 個の異なるテーブルの範囲にマップされます。
各テーブルの基本構造は、EventId (bigint) と PartitionKey (int) で構成される複合クラスター化主キーであり、その後にいくつかのインデックスのない列が続きます。EventId は一意で、すべてのテーブルで単調に増加し、シーケンスで実装されます。PartitionKey はパーティション テーブルごとに一意であるため、各テーブルのチェック制約は単純に "CHECK (PartitionKey = x)" であり、x はパーティション テーブルごとに定義されます。これにより、パーティション キーを指定して検索範囲を狭めることができない場合でも、クラスター化インデックス シークを介して EventId を検索できます。EventId と PartitionKey の両方を提供できる場合、オプティマイザーはパーティション キーに一致する単一のテーブルに対してのみインデックス シークを実行できるため、クエリは非常に効率的です。
実験
イベントの日に基づいてさらに細かく分割し、より幅広い属性の組み合わせ (前述の 2 ~ 3 の代わりに 500 ~ 5000) を作成できれば、私の生活はさらに楽になります。 10,000 ~ 50,000 の異なるパーティションの範囲。20,000 の異なるテーブルを持つデータベースでこれをテストしたところ、残念ながら、さまざまな操作の実行時間が、テーブルの数に比例して増加することがわかりました。クエリ統計によると、ほとんどの時間は、クエリの実行ではなく、クエリの解析とコンパイルに費やされました。
さまざまな操作で見つけた実行時間は次のとおりです(初歩的な表を許してください):
- 分割ビューを作成する
100 tables : 50ms
1000 tables : 800ms
2000 tables : 2,660ms
4000 tables : 10,000ms
16000 tables: 225,000ms
select * from PartitionedView where EventId = x
(すべてのテーブルをスキャン)100 tables : 78ms parse/compile time; 25ms exec time
1000 tables : 3,500ms parse/compile time; 160ms exec time
2000 tables : 15,000ms parse/compile time; 500ms exec time
4000 tables : 68,000ms parse/compile time; 2,000ms exec time
16000 tables:
解析/コンパイル時間が 10 分を超えるとキャンセルされました!
select * from PartitionedView where (EventId = x) and (PartitionKey = y)
(1 つのテーブルのみをスキャン)100 tables : 74ms parse/compile time; 1ms exec time
1000 tables : 2,500ms parse/compile time; 15ms exec time
2000 tables : 11,000ms parse/compile time; 10ms exec time
4000 tables : 50,000ms parse/compile time; 16ms exec time
16000 tables:
解析/コンパイル時間が 10 分を超えるとキャンセルされました!
質問
あれだけのテーブルを使うことを考えても、叱られるべきですか?そうでない場合、多数のテーブルが存在するときにクエリの解析とコンパイルの時間を短縮する方法はありますか?