web-dev-qa-db-ja.com

巨大なテーブルの列タイプを変更する

SQL Server 2008 R2に、10億行近くのテーブルがあります。 2つの列のデータ型をintからbigintに変更したいと思います。二度 ALTER TABLE zzz ALTER COLUMN yyyは機能しますが、非常に遅いです。どうすればプロセスをスピードアップできますか?データを別のテーブルにコピーし、ドロップ、作成、コピーバックして単純リカバリモードに切り替えるか、カーソルを使って1000行ずつ実行することを考えていましたが、実際に改善されるかどうかはわかりません。

18
user1417408

行っている変更によっては、メンテナンスウィンドウを使用する方が簡単な場合があります。そのウィンドウ(誰もテーブルのデータを変更できないはずです)の間、次のことができます。

  1. 古い列を指すインデックス/制約をすべて削除し、トリガーを無効にします
  2. 新しいデータ型の新しいnullable列を追加します(NOT NULLを意味する場合でも)
  3. 新しい列を更新して、古い列の値と同じに設定します(これは、個々のトランザクションのチャンクで行うことができます(たとえば、UPDATE TOP (10000) ... SET newcol = oldcol WHERE newcol IS NULLを使用して一度に10000行に影響を与えます)。また、ログのオーバーランを回避するためにCHECKPOINTを使用します)
  4. 更新がすべて完了したら、古い列を削除します
  5. 新しい列の名前を変更します(必要に応じてNOT NULL制約を追加します)
  6. インデックスの再構築と統計の更新

ここで重要なのは、ステップ3で段階的に更新を実行できることです。これは、単一のALTERTABLEコマンドでは実行できません。

これは、列がデータの整合性において主要な役割を果たしていないことを前提としています。列が外部キーの関係の束に関与している場合は、さらに多くの手順があります。

[〜#〜]編集[〜#〜]

また、大声で疑問に思っているので、これについてはテストを行っていません(ただし、リストに追加しています)。ページ+行の圧縮がここで役立つかどうか疑問に思いますか? INTをBIGINTに変更した場合でも、圧縮が適用されていると、SQLServerはすべての値をINTに収まるかのように処理する必要があります。繰り返しになりますが、これによって変更が速くなるか遅くなるか、またはそもそも圧縮を追加するのにどれだけ時間がかかるかについてはテストしていません。そこに捨てるだけです。

29
Aaron Bertrand