行版本控制为每行维护 14 个字节的内部版本控制信息。但这真的是每行的成本,还是也适用于表上每个索引的成本?
似乎这 14 个字节也必须添加到所有索引记录中,以便仅索引扫描(和其他仅索引访问)可以看到版本控制信息并感知数据的时间点快照。
不过,我在网上可以找到的所有信息都只讨论了每行 14 字节的开销。
行版本控制为每行维护 14 个字节的内部版本控制信息。但这真的是每行的成本,还是也适用于表上每个索引的成本?
似乎这 14 个字节也必须添加到所有索引记录中,以便仅索引扫描(和其他仅索引访问)可以看到版本控制信息并感知数据的时间点快照。
不过,我在网上可以找到的所有信息都只讨论了每行 14 字节的开销。
为什么要将它添加到所有索引记录中?您是指所有索引,还是所有索引的所有行?
只有受影响索引的受影响行将获得 14 字节标记。
这里有3个例子。
假设我们有 100 页的聚簇表(带有
id int PK
)和 1 个非聚簇索引(在另一列上Col1
),并且我们更改了聚簇索引的 10 个键 (id
)。聚簇表的所有 10 行都将获得行版本标记(10 行,而不是 100 行),非聚簇索引受影响的 10 行将具有此标记,因为每个非聚簇索引至少在叶级包含聚簇索引键,因此 10 行非聚集索引也会有它们的版本。
您可以通过更改在数据库中具有非聚集索引的聚集表中的 10 行
RCSI
并通过检查来向自己证明这一点sys.dm_tran_version_store
:将有 20 行,您将能够通过大小区分聚集索引行和非聚集索引行。..................................................... .
Col1
现在假设我们有同一个表,其中有 100 行,并且在同一列上有非聚集索引。现在我们制作这个堆update
的列。id
如果您现在检查
sys.dm_tran_version_store
,您将只看到 10 行,它们是一个堆的 10 行,根本没有索引行。这是因为当我们更新 10 时我们的索引Col1
没有改变id
。在这种情况下,我们id
对具有 RID 作为指向叶级堆的后向指针的非聚集索引没有影响。当然,如果我们的非聚集索引有
id
作为键字段或包含字段,update
也会id
影响该索引,在这种情况下我们会row version store
再次找到 20 行。..................................................... .
示例 N3:具有结构 Col1、Col2、Col3 的表。索引:ix_1 (Col1), ix_3(Col3)。
我们更新未出现在任何索引中的 Col2。只有表中受影响的行才会获得行版本标记,ix_1 和 ix_3 根本不会受到影响。
正如 Solomon Rutzky 在他的评论中指出的那样,这些版本标签将出现在索引中,直到
INDEX REBUILD
.以下是本书的引文:Pro SQL Server Internals By Dmitri Korotkevitch