8

巨大なファクト テーブルがあり、新しいディメンションを追加したい場合は、次のように実行できます。

BEGIN TRANSACTION

ALTER TABLE [GiantFactTable]
ADD NewDimValueId INT NOT NULL
CONSTRAINT [temp_DF_NewDimValueId] DEFAULT (-1)
WITH VALUES -- table is not actually rebuilt!

ALTER TABLE [GiantFactTable]
WITH NOCHECK
ADD CONSTRAINT [FK_GiantFactTable_NewDimValue]
FOREIGN KEY ([NewDimValueId])
REFERENCES [NewDimValue] ([Id])

-- drop the default constraint, new INSERTs will specify a value for NewDimValueId column
ALTER TABLE [GiantFactTable]
DROP CONSTRAINT [temp_DF_NewDimValueId]

COMMIT TRANSACTION

注意: 上記はすべて、テーブルのメタデータを操作するだけであり、テーブルのサイズに関係なく高速である必要があります。GiantFactTable.NewDimValueId次に、FK に違反しないように、小さなトランザクションをバックフィルするジョブを実行できます。(この時点で、すべての INSERT/UPDATE (バックフィル操作など) は有効になっているため、FK によって検証されますが、「信頼されている」わけではありません)

バックフィルの後、データが一貫していることがわかります。私の質問は、SQL エンジンもどのように対応できるようになるかということです。テーブルをオフラインにすることなく。

このコマンドは FK を信頼済みにしますが、スキーマ変更 (Sch-M) ロックが必要であり、テーブルをオフラインにするのに数時間 (数日?) かかる可能性があります。

ALTER TABLE [GiantFactTable]
WITH CHECK CHECK CONSTRAINT [FK_GiantFactTable_NewDimValue]

ワークロードについて: テーブルには数百のパーティション (固定数) があり、データは一度に 1 つのパーティションに (ラウンドロビン方式で) 追加され、削除されることはありません。また、クラスタリング キーを使用して、一度に 1 つのパーティションから (比較的小さい) 範囲の行を取得する一定の読み取りワークロードもあります。一度に 1 つのパーティションをチェックしてオフラインにすることは許容されます。しかし、これを行うための構文が見つかりません。他のアイデアはありますか?

4

1 に答える 1

1

いくつかのアイデアが思い浮かびますが、それらはきれいではありません。

ワークロードをリダイレクトし、CHECK 制約をオフラインで実行する

  1. 同じ構造の新しいテーブルを作成します。
  2. 「挿入」ワークロードを変更して、新しいテーブルに挿入します
  3. 「読み取り」ワークロードで使用されるパーティションから新しいテーブル (または同じ構造を持つ 3 番目のテーブル) にデータをコピーします。
  4. 新しいテーブルを使用するように「読み取り」ワークロードを変更します
  5. 実行alter tableして制約を確認し、必要なだけ実行します
  6. 両方のワークロードをメイン テーブルに戻します。
  7. 新しい行をメイン テーブルに挿入します。
  8. 新しいテーブルを削除

上記のバリエーションは、ステップ 3 で関連するパーティションを新しいテーブルに切り替えることです。これは、データをコピーするよりも高速であるはずですが、制約がチェックされた後にデータをコピーする (切り替えるだけでなく) 必要があると思います。 .

すべてのデータを新しいテーブルに挿入する

  1. 同じ構造と制約を有効にして新しいテーブルを作成する
  2. 「挿入」ワークロードを新しいテーブルに変更します
  3. すべてのデータを古いテーブルから新しいテーブルにバッチでコピーし、完了するまで待ちます
  4. 「読み取り」ワークロードを新しいテーブルに変更します。ステップ 3 に時間がかかりすぎて、「読み取り」ワークロードが新しいテーブルに挿入された行のみを必要とする場合は、この切り替えを手動で管理する必要があります。
  5. 古いテーブルをドロップ

索引を使用して制約チェックを高速化しますか?

これが機能するかどうかはわかりませんが、外部キー列に非クラスター化インデックスを作成してみてください。また、外部キーによって参照されるテーブルの関連する一意のキーにインデックスがあることを確認してください。コマンドは、alter tableそれらを使用してチェックを高速化できる場合があります (少なくとも、完全なテーブル スキャンを実行する場合と比較して IO を最小限に抑えることによって)。もちろん、中断を避けるためにインデックスをオンラインで作成することもできます。

于 2013-11-04T01:53:39.973 に答える