4

何百万ものテーブルがあり、一部のテーブルでは数十億の行があり、1 つの列が int で、bigint に変更しています。SSMS を使用してデータ型を変更しようとしましたが、トランザクション ログがいっぱいになり、数時間後に失敗しました。

私がとった別のアプローチは、新しい列を作成し、プロパティを100000に設定することで、古い列から新しい列に値をバッチで更新し始めることですROWCOUNT。これは機能しますが、非常に遅く、サーバーメモリがいっぱいです。このアプローチでは、完了するまでに数日かかる場合があり、本番環境では受け入れられません。

データ型を変更するための高速\最良の方法は何ですか? ソース列は ID 列ではなく重複しており、null が許可されています。テーブルには他の列にインデックスがあります。インデックスを無効にするとプロセスが高速化されますか? Begin Tran と Commit を追加すると役に立ちますか?

4

2 に答える 2

7

変更を行うために必要な実際の時間を示すALTERCOLUMNのテストを実行しました。結果は、ALTER COLUMNが瞬時ではなく、必要な時間が直線的に増加することを示しています。

RecordCt    Elapsed Mcs
----------- -----------
      10000      184019
     100000     1814181
    1000000    18410841

私の推奨は、あなたが提案したようにそれをバッチ処理することです。新しい列を作成し、 ROWCOUNTWAITFORの組み合わせを使用して、時間の経過とともに列に事前入力します。

WAITFOR値がテーブルから読み取られるように、スクリプトをコーディングします。そうすれば、本番サーバーがダウンし始めたときに、WAITFOR値をオンザフライで変更できます。オフピーク時にWAITFORを短縮できます。(DMVを使用してWAITFOR値を自動化することもできますが、これは確かにより複雑です。)

これは複雑な更新であり、計画と多くのベビーシッターが必要になります。

ロブ


これがALTERCOLUMNテストコードです。

USE tempdb;
SET NOCOUNT ON;
GO
IF EXISTS (SELECT * FROM sys.tables WHERE [object_id] = OBJECT_ID('dbo.TestTable'))
    DROP TABLE dbo.TestTable;
GO
CREATE TABLE dbo.TestTable (
    ColID   int              IDENTITY,
    ColTest int              NULL,
    ColGuid uniqueidentifier DEFAULT NEWSEQUENTIALID()
);
GO

INSERT INTO dbo.TestTable DEFAULT VALUES;
GO 10000

UPDATE dbo.TestTable SET ColTest = ColID;
GO

DECLARE @t1 time(7) = SYSDATETIME();
DECLARE @t2 time(7);

ALTER TABLE dbo.TestTable ALTER COLUMN ColTest bigint NULL;

SET @t2 = SYSDATETIME();

SELECT
    MAX(ColID)              AS RecordCt,
    DATEDIFF(mcs, @t1, @t2) AS [Elapsed Mcs]
FROM dbo.TestTable;
于 2012-04-16T22:09:03.753 に答える
0

シンプルalter table <table> alter column <column> bigint nullは基本的に時間がかかりません。変換の問題やnullチェックはありません-なぜこれが比較的瞬時に行われないのかわかりません

GUI から実行すると、一時テーブルを作成し、既存のテーブルを削除して、新しいテーブルを作成しようとする可能性があります。絶対に行わないでください。

于 2012-04-16T20:58:34.213 に答える