sql Server 2012上的“ALTER INDEX ALL REBUILD”操作失败,因为事务日志空间不足.索引从未被重组或重建,因此几乎所有索引的碎片都超过80%.
DB使用简单的恢复模型.我假设在命令的“ALL”形式执行每个索引操作之后,将在下一个索引重建之前刷新事务日志数据.它是如何实际工作的,还是将索引重建记录为好像它们是单个事务的一部分?
换句话说,我可以通过编写脚本来单独执行每次重建来减少事务日志增长吗?还有其他因素需要考虑吗?
解决方法
I assumed that following each index operation performed by the “ALL” form of the command,the transaction log data would be flushed prior to the next index rebuild. Is that how it actually works,or are the index rebuilds logged as if they are part of a single transaction?
1)日志刷新:SIMPLE恢复模型不会在每次事务后清除日志,而是在检查点. (link更多信息)
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')
现在,您可以比较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
请注意,在REBUILD ALL结束之前,第一个打开的事务(事务ID 0000:000002fa)是如何提交的,但是对于逐个索引的重建,它们是连续提交的.