1億2000万レコードのテーブルを更新する唯一の正しい方法は、SELECT
を使用することです。 秒を入力するステートメント テーブル。これを行うときは注意する必要があります。以下の手順。
シンプルなケース
クラスタ化インデックスがないテーブルの場合、同時DMLがない時間中:
-
SELECT *, new_col = 1 INTO clone.BaseTable FROM dbo.BaseTable
- 新しいテーブルにインデックスや制約などを再作成します
- ALTER SCHEMA...TRANSFERを使用して新旧を切り替えます。
- 古いテーブルを削除する
クローンスキーマを作成できない場合は、同じスキーマ内の別のテーブル名で作成できます。切り替え後、すべての制約とトリガー(該当する場合)の名前を変更することを忘れないでください。
単純ではないケース
まず、BaseTable
を再作成します clone.BaseTable
など、別のスキーマで同じ名前を使用する 。別のスキーマを使用すると、後で名前変更プロセスが簡素化されます。
- クラスター化されたインデックスを含める 、 該当する場合。主キーと一意の制約がクラスター化される場合がありますが、必ずしもクラスター化されるとは限りません。
- ID列と計算列を含める 、該当する場合。
- 新しいINT列を含める 、どこに属していても。
- 含めないでください 次のいずれか:
- トリガー
- 外部キーの制約
- 非クラスター化インデックス/主キー/一意の制約
- 制約またはデフォルトの制約を確認します。デフォルトではあまり違いはありませんが、最小限に抑えるようにしています。
次に、1000行の挿入をテストします:
-- assuming an IDENTITY column in BaseTable
SET IDENTITY_INSERT clone.BaseTable ON
GO
INSERT clone.BaseTable WITH (TABLOCK) (Col1, Col2, Col3)
SELECT TOP 1000 Col1, Col2, Col3 = -1
FROM dbo.BaseTable
GO
SET IDENTITY_INSERT clone.BaseTable OFF
結果を調べます。すべてが順番に表示される場合:
- クローンテーブルを切り捨てる
- データベースが一括ログまたは単純なリカバリモデルになっていることを確認してください
- 完全な挿入を実行します。
これにはしばらく時間がかかりますが、更新ほど長くはありません。完了したら、クローンテーブルのデータをチェックして、すべてが正しいことを確認します。
次に、クラスター化されていないすべての主キー/一意の制約/インデックスと外部キーの制約を(この順序で)再作成します。必要に応じて、デフォルトを再作成し、制約を確認します。すべてのトリガーを再作成します。各制約、インデックス、またはトリガーを別々のバッチで再作成します。例:
ALTER TABLE clone.BaseTable ADD CONSTRAINT UQ_BaseTable UNIQUE (Col2)
GO
-- next constraint/index/trigger definition here
最後に、dbo.BaseTable
を移動します バックアップスキーマとclone.BaseTable
に dboスキーマ(またはテーブルが存在するはずの場所)に移動します。
-- -- perform first true-up operation here, if necessary
-- EXEC clone.BaseTable_TrueUp
-- GO
-- -- create a backup schema, if necessary
-- CREATE SCHEMA backup_20100914
-- GO
BEGIN TRY
BEGIN TRANSACTION
ALTER SCHEMA backup_20100914 TRANSFER dbo.BaseTable
-- -- perform second true-up operation here, if necessary
-- EXEC clone.BaseTable_TrueUp
ALTER SCHEMA dbo TRANSFER clone.BaseTable
COMMIT TRANSACTION
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE() -- add more info here if necessary
ROLLBACK TRANSACTION
END CATCH
GO
ディスクスペースを解放する必要がある場合は、この時点で元のテーブルを削除できますが、しばらくの間保持するのが賢明かもしれません。
言うまでもなく、これは理想的にはオフラインです。 手術。この操作の実行中にデータを変更する人がいる場合は、スキーマスイッチを使用して補正操作を実行する必要があります。 dbo.BaseTable
でトリガーを作成することをお勧めします すべてのDMLを別のテーブルに記録します。挿入を開始する前に、このトリガーを有効にしてください。次に、スキーマ転送を実行するのと同じトランザクションで、ログテーブルを使用して補正を実行します。最初にデータのサブセットでこれをテストしてください!デルタは簡単に台無しになります。