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


12

最近、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

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

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


アイデアをありがとう。私はほとんどチェック制約を追加しましたが、週末にメンテナンスウィンドウがあり、列をnull不可に変更することができました。私はそれが助けたかどうかはわかりませんが、列をnull不可にする直前にテーブルデータをバッファプールに取得しようとすると、SELECT c1, count(*) FROM t1 GROUP BY c1実行に約9分かかりました。その後の実際のALTER TABLE ALTER COLUMNステートメントは、完了するのに25分かかりました。悪くない。
ベン・アマダ

11

Enterprise Edition(EE)を使用NOT NULLしている場合、デフォルトの0or 1(最も一般的なもの)のように追加する方が良い戦略かもしれません。

これは、EEのメタデータのみの変更です。次に、反転する必要があるものを更新します。これは、更新が少なくなり、終了時に列のヌル可能性を変更する必要がないことを意味します。- マーティン・スミス


興味深いことに、先週、SQL Developer Editionを実行しているローカルマシン上の同じ大きなテーブルに、null不可のビット列をデフォルト値で追加することをテストしたときに、この機能に気付きました-列はすぐに追加され、理由を理解できませんでした。開発者版にはEE機能が含まれているため、それが必要であると後で彼に言われました。
ベン・アマダ

-3

データを新しいテーブルにコピーしてから、名前を変更してください。制約とインデックスに注意する必要があります。これは、SSMSテーブルデザイナが列を並べ替えるとき(たとえば)に行うことですが、正しくないものがないかどうかをスクリプトで確認する必要があります。

コピー中、ソーステーブルへの読み取りアクセスは問題ありませんが、書き込みがある場合は、分離レベルに応じてブロックされるかコピーされない場合があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.