web-dev-qa-db-ja.com

生産テーブルへの列の追加

SQL Server 2008 R2で大規模な運用テーブルに列を追加する最良の方法は何ですか?マイクロソフトのオンライン書籍によると:

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

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

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

29
sh-beta

"場合によります"

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

たとえば、intまたはcharを追加するには、物理​​的な行の移動が必要です。デフォルトのないnull可能varcharを追加しないでください(NULLビットマップを展開する必要がある場合を除く)。

見積もりを取得するには、本番環境の復元されたコピーでそれを試す必要があります

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

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

最初にバックアップを取ると言ったのですか?

27
gbn

列がNULL可能である場合、影響はごくわずかです。列をNULLにすることができず、値を設定する必要がある場合は、まったく異なる可能性があります。この場合、私は、null以外のデフォルトの制約を一度に追加するのではなく、すべての行にデータを効果的に追加します。

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

プロダクションのコピーを復元し、そこで試すことでこれをテストできるという@gbnに同意します...タイミングの良いアイデアが得られ(ハードウェアはある程度似ていると想定)、トランザクションログへの影響も確認できます。

21
Aaron Bertrand

検討しましたか:

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

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

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

4
RobPaller

言及する必要があると思う特別な例外があります。

SQL Server 2012 Enterprise以降では、ランタイム定数を使用して新しいNOT NULL列を追加すると、オンライン操作が即座に完了し、テーブルの行数。

これに関する詳細は [〜#〜] msdn [〜#〜] にあります

重要なセクションを再現します

SQL Server 2012(11.x)Enterprise Edition以降、デフォルト値がランタイム定数の場合、デフォルト値を含むNOT NULL列の追加はオンライン操作です。これは、テーブルの行数に関係なく、操作がほぼ瞬時に完了することを意味します。なぜなら、テーブルの既存の行は操作中に更新されないからです。代わりに、デフォルト値はテーブルのメタデータにのみ保存され、値はこれらの行にアクセスするクエリで必要に応じて検索されます。

1
rince