web-dev-qa-db-ja.com

大きなテーブルの列をNON NULLに変更する速度を上げる

最近、5億行に近いNULL可能なビット列をテーブルに追加しました。列にはデフォルトはありませんが、すべての挿入は0または1の値を指定しています。1回限りのルーチンを実行して、既存のすべての行に0または1を割り当てました(行を小さなバッチで更新)。これで、すべての行のその列に0または1が含まれるはずです。

ビット列をnullにできないようにしたいのですが、ALTER TABLE t1 ALTER COLUMN c1 bit not nullを使用して試行したところ、3分間実行され、テーブルへのすべての読み取りをブロックしていたため、停止しました。完了するのに長い時間がかかります。それほど長くはかからない可能性もありますが、利用できなくなるリスクはあまりありませんでした。ロールバック自体には6分かかりました。

完了するまでに数時間かかる可能性のある列をnullにできないようにする方法について何か提案はありますか?さらに、ALTER TABLE ALTER COLUMNステートメントを開始してから開始するまでの時間を見積もる方法はありますか?キャンセルは完了するのにかかりますか?

SQL Server 2017 Web Editionを使用しています。

12
Ben Amada

列定義を変更する代わりに、 CHECK CONSTRAINT これは、その列にNULLを許可しません。テーブルは引き続きスキャンする必要がありますが、すべてのデータページを変更する必要がないため、はるかに高速な操作になります。残念ながら、操作中はSch-Mロックが保持されます。 1つのトリックは、制約を追加する前に、テーブルのできるだけ多くをバッファー・プールに入れようとすることです。これにより、Sch-Mロックが保持される時間を短縮できます。

その後、制約を削除して、次のメンテナンスウィンドウで列定義を変更できます。

12
Joe Obbish

Enterprise Edition(EE)を使用している場合は、NOT NULLとして追加し、デフォルトで0または1(最も一般的)として追加することをお勧めします。

これは EEのメタデータのみの変更 です。次に、反転する必要があるものを更新します。つまり、更新が少なくなり、終了時に列のnull値を変更する必要がなくなります。 - martin-smith

11
user126897