実動テーブルへの列の追加


28

SQL Server 2008 R2の大規模な運用テーブルに列を追加する最良の方法は何ですか?オンラインのMicrosoftの本によると:

ALTER TABLEで指定された変更はすぐに実装されます。変更がテーブル内の行の変更を必要とする場合、ALTER TABLEは行を更新します。ALTER TABLEは、テーブルのスキーマ変更ロックを取得して、最後に非常に短いSCH-Mロックを必要とするオンラインインデックス操作を除き、変更中に他の接続がテーブルのメタデータを参照しないようにします。

(http://msdn.microsoft.com/en-us/library/ms190273.aspx)

数百万行の大きなテーブルでは、これには時間がかかる場合があります。停止することが唯一の選択肢ですか?このような状況に対処する最善の方法は何ですか?


1
この問題に関する最近の記事:sqlservercentral.com/articles/Change+Tracking/74397
8kb

回答:


27

"場合によります"

行にデータを追加する必要のない列を追加すると、非常に高速になります。

たとえば、intまたはcharを追加するには、物理​​的な行の移動が必要です。デフォルトなしでNULL可能varcharを追加することはできません(NULLビットマップを展開する必要がない限り)

推定値を取得するには、本番環境の復元コピーで試してみる必要があります

10億行のテーブルにインデックスとキーを再追加する必要がある場合、新しいテーブルの作成、コピー、名前の変更に時間がかかることがあります。

NULL許容列を追加するのに数秒かかった10億行のテーブルを変更しました。

最初にバックアップを取ると言いましたか?


2
バックアップで+1。また、十分なログ領域があることを確認してください。
SqlACID

intまたはcharを追加するために物理的な行の移動が必要な理由を明確にできますか?
shベータ

5
「2行目の行にデータを追加する必要がない」という意味ですか?
ベンブロッカ

21

列がNULL可能であれば、影響は無視できるはずです。列をNULLにすることはできず、値を設定する必要がある場合、まったく異なる可能性があります。この場合、1回のショットでnot nullおよびデフォルトの制約を追加する代わりに、すべての行にデータを効果的に追加します。

  • NULL可能として列を追加します-ほとんどの場合、高速である必要があります
  • 値をデフォルトに更新します
    • 必要に応じてバッチでこれを行うことができます
    • また、これを使用して、一部の行がデフォルトにならない場合がある条件付きロジックを適用することもできます
  • NOT NULL /デフォルト制約を追加します
    • これは、どのデータもNULLでない場合は高速になりますが、測定可能です

@gbnに同意して、実稼働環境のコピーを復元して試してみてください...ハードウェアが多少似ていると仮定すると、タイミングの良いアイデアが得られ、トランザクションログへの影響も確認できます。


最後のビットについて:•add the not null/default constraintsこれに潜在的な問題がないかわかりません... MSSQL(2008R2でさえ)がnot null列をnullに変更するとき、トレースを置くと、実際にそれが見えますテーブルのすべての行を完全に更新します。つまりupdate table1 set column1 = column1、完全にばかげた方法で非ヌル検証を実行していると仮定します。このトランザクションはテーブルの2倍のサイズ(ページの前後)であるため、DWテーブルの場合は巨大になる可能性があります。以前は、データをbcpし、切り捨て、nullから非nullへの変更を行ってから、bcpを入力する必要がありました

誰かがこれを回避する方法を知っているなら、私は知っています...対照的に、Oracleでは、nullをnot nullに変更するとロックが行われ、次に非nullがないことを確認する選択が行われ、次に純粋なメタデータが瞬時に更新されます。

ちょっと@マイク、これはそれ自体で良い潜在的な質問のように聞こえます。
デレクダウニー

4

考慮しましたか:

  1. テーブル定義への変更を含む新しいテーブルを作成します。
  2. 元のテーブルから選択して、新しいテーブル定義に挿入します。
  3. 元のテーブルの名前を_origに変更してから、新しいテーブルの名前を元のテーブル名に変更します。

ここでの欠点は、この変更を行うためにデータベースに十分なスペースが必要なことです。ダーティリードを防ぐために、テーブルの読み取りロックが必要になる場合があります。

ただし、元のテーブルに同時にアクセスする機会または必要がある場合、エンドユーザーへの影響を最小限に抑えます。また、ロック期間を最小限に抑える必要があります。


読み取るのではなく、書き込みロックが必要ではないでしょうか?ユーザーが古いテーブルのデータを見るのは問題ありません。バッファスワップの終了時に上書きされる変更をコミットしたくないだけです。
ジョンオブオールトレードズ

それは、データウェアハウスの帽子で、変更を少し簡単に制御できる場所についての私の考えでした。OLTPの状況では、テーブルに変更が加えられないようにするために、書き込みロックが必要になります。
-RobPaller
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.