在更改表期间耗尽事务日志空间

Mat*_*les 4 alter-table azure-sql-database transaction-log

我正在运行一个更改表,更改包含近 3000 万行的表上的列,SQL Azure 在大约 18 分钟后失败,说 The session has been terminated because of excessive transaction log space usage. Try modifying fewer rows in a single transaction.

我猜不可能将其分解为一次修改更少的行,所以我想知道对数据库进行此更改的选项是什么。SQL Azure 不允许我更改事务日志的大小(限制为 1GB)。

我猜我最好的办法是创建一个具有新布局的新表,将数据迁移到该表中,删除原始表,然后重命名新表以匹配旧表的名称。如果是这种情况,如何最好地构建这些命令?

我们系统的计划停机时间目前不是问题,因此此操作可以根据需要进行。

SQL*_*tar 5

您需要将数据加载到新表中,以小批量方式执行此操作,然后删除现有表。我使用 AdventureWorks 中的 Sales.Customer 表整理了一个快速示例,类似的东西也适用于您。

首先,创建新表,并使用要使用的新数据类型完成:

CREATE TABLE [Sales].[Currency_New](
    [CurrencyCode] [nchar](4) NOT NULL,
    [Name] [varchar](128) NOT NULL,
    [ModifiedDate] [datetime] NOT NULL,
 CONSTRAINT [PK_Currency_New_CurrencyCode] PRIMARY KEY CLUSTERED 
(
    [CurrencyCode] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
)
GO
Run Code Online (Sandbox Code Playgroud)

然后,插入您的记录并定义您的批次。我在这里使用 10,但您可能想要使用更大的数据,比如一次 10,000 行。对于 30MM 行,我什至建议您一次使用 100k 行批处理大小,这是我通常用于较大表的限制:

DECLARE @RowsInserted INT, @InsertVolume INT
SET @RowsInserted = 1
SET @InsertVolume = 10 --Set to # of rows

WHILE @RowsInserted > 0
BEGIN       

INSERT INTO [Sales].[Currency_New] ([CurrencyCode]
           ,[Name]
           ,[ModifiedDate])
SELECT TOP (@InsertVolume)
       SC.[CurrencyCode]
           ,SC.[Name]
           ,SC.[ModifiedDate]
FROM [Sales].[Currency] AS SC
LEFT JOIN [Sales].[Currency_New] AS SCN 
    ON SC.[CurrencyCode] = SCN.[CurrencyCode] 
WHERE SCN.[CurrencyCode] IS NULL

SET @RowsInserted = @@ROWCOUNT
END
Run Code Online (Sandbox Code Playgroud)

在清理之前,我通常会进行完整性检查并验证行数是否相同:

SELECT COUNT(*) FROM [Sales].[Currency] 
SELECT COUNT(*) FROM [Sales].[Currency_New]
Run Code Online (Sandbox Code Playgroud)

一旦您确信已经迁移了数据,就可以删除原始表:

DROP TABLE [Sales].[Currency]
Run Code Online (Sandbox Code Playgroud)

最后一步,重命名新表,这样用户就不必更改任何代码:

EXEC sp_rename '[Sales].[Currency_New]', '[Sales].[Currency]';
GO
Run Code Online (Sandbox Code Playgroud)

我不知道这需要多久。当您有一个清晰的维护窗口并且用户未连接时,我建议您尝试这样做。

HTH