ALTER INDEX ALL REBUILD 是否比单独重建每个索引使用更多的事务日志空间和简单的恢复模型?

Goo*_*ail 18 index sql-server

SQL Server 2012 上的“ALTER INDEX ALL REBUILD”操作失败,因为事务日志空间不足。索引从未重组或重建,因此几乎所有索引的碎片化率都超过 80%。

DB 使用简单的恢复模型。我假设在“ALL”形式的命令执行每个索引操作之后,事务日志数据将在下一次索引重建之前被刷新。这是它实际工作的方式,还是索引重建记录为好像它们是单个事务的一部分?

换句话说,我可以通过编写脚本来单独执行每个重建来减少事务日志的增长吗?还有其他因素需要考虑吗?

For*_*est 16

我假设在“ALL”形式的命令执行每个索引操作之后,事务日志数据将在下一次索引重建之前被刷新。这是它实际工作的方式,还是索引重建记录为好像它们是单个事务的一部分?

1) 日志刷新:SIMPLE 恢复模型不会在每个事务之后清除日志,而是在检查点。(更多信息的链接

2a) REBUILD ALL:是的,REBUILD ALL 作为单个事务工作。索引重建有自己的事务,但整个操作直到最后才完全提交。所以是的,您可以通过重建单个索引(并可能发出 CHECKPOINT 命令)来限制日志文件的增长。

2b) 证明!在这里,有一个演示脚本。(建于2016年开发)首先,建立一个测试数据库,有表和索引:

USE master
GO

CREATE DATABASE Test_RebuildLog
GO

ALTER DATABASE Test_RebuildLog
SET RECOVERY SIMPLE
GO

USE Test_RebuildLog
GO

CREATE TABLE IndexTest
(ID int identity(1,1),
a char(1),
b char(1))

CREATE CLUSTERED INDEX CIX_IndexTest_ID ON IndexTest(ID)
CREATE INDEX IX_IndexTest_a ON IndexTest(a)
CREATE INDEX IX_IndexTest_b ON IndexTest(b)

INSERT IndexTest
(a,b)
VALUES ('a','b'),('z','y'),('s','r')
Run Code Online (Sandbox Code Playgroud)

现在您可以比较 REBUILD ALL 和单独重建之间的日志活动

CHECKPOINT
GO
ALTER INDEX ALL ON IndexTest REBUILD

SELECT *
FROM sys.fn_dblog(NULL,NULL)
WHERE Operation = 'LOP_COMMIT_XACT'
OR Operation = 'LOP_BEGIN_XACT'
GO

CHECKPOINT
GO
ALTER INDEX CIX_IndexTest_ID ON IndexTest REBUILD
ALTER INDEX IX_IndexTest_a ON IndexTest REBUILD
ALTER INDEX IX_IndexTest_b ON IndexTest REBUILD

SELECT *
FROM sys.fn_dblog(NULL,NULL)
WHERE Operation = 'LOP_COMMIT_XACT'
OR Operation = 'LOP_BEGIN_XACT'
GO
Run Code Online (Sandbox Code Playgroud)

请注意第一个打开的事务(对我来说是事务 ID 0000:000002fa)是如何直到 REBUILD ALL 结束才提交的,但是对于逐个索引重建,它们是连续提交的。