正如@Souplex在评论中所暗示的,一个可能的解释可能是,如果此列是NULL
它所参与的非聚集索引中的第一个-able列。
对于以下设置
CREATE TABLE Foo
(
A UNIQUEIDENTIFIER NOT NULL DEFAULT NEWSEQUENTIALID() PRIMARY KEY,
B CHAR(1) NOT NULL DEFAULT 'B'
)
CREATE NONCLUSTERED INDEX ix
ON Foo(B);
INSERT INTO Foo
(B)
SELECT TOP 100000 'B'
FROM master..spt_values v1,
master..spt_values v2
sys.dm_db_index_physical_stats显示非聚集索引ix
具有248个叶页和一个根页。
索引叶子页中的典型行看起来像
并在根页面中
然后跑步...
CHECKPOINT;
GO
ALTER TABLE Foo ALTER COLUMN B CHAR(1) NULL;
SELECT Operation,
Context,
ROUND(SUM([Log Record Length]) / 1024.0,1) AS [Log KB],
COUNT(*) as [OperationCount]
FROM sys.fn_dblog(NULL,NULL)
WHERE AllocUnitName = 'dbo.Foo.ix'
GROUP BY Operation, Context
回来
+-----------------+--------------------+-------------+----------------+
| Operation | Context | Log KB | OperationCount |
+-----------------+--------------------+-------------+----------------+
| LOP_SET_BITS | LCX_GAM | 4.200000 | 69 |
| LOP_FORMAT_PAGE | LCX_IAM | 0.100000 | 1 |
| LOP_SET_BITS | LCX_IAM | 4.200000 | 69 |
| LOP_FORMAT_PAGE | LCX_INDEX_INTERIOR | 8.700000 | 3 |
| LOP_FORMAT_PAGE | LCX_INDEX_LEAF | 2296.200000 | 285 |
| LOP_MODIFY_ROW | LCX_PFS | 16.300000 | 189 |
+-----------------+--------------------+-------------+----------------+
再次检查索引叶行现在看起来像
以及上层页面中的行,如下所示。
每行已更新,现在包含两个字节的列数以及另一个字节的NULL_BITMAP。
由于额外的行宽,非聚簇索引现在具有285个叶页,并且现在具有两个中间级页以及根页。
的执行计划
ALTER TABLE Foo ALTER COLUMN B CHAR(1) NULL;
看起来如下
这将创建索引的全新副本,而不是更新现有索引并需要拆分页面。