got*_*tqn 3 t-sql sql-server-2012
我最近了解了sp_tableoption,它使您能够为特定表存储“行外大值类型”。
我的一个同事告诉我,如果我启用它,每个字段至少存储在 8 KB 页面上,无论它有多大。我无法找到对此的确认,因此我运行了以下测试:
DROP TABLE Size
CREATE TABLE Size
(
[ID] TINYINT
,[Text] NVARCHAR(MAX)
)
EXEC sp_tableoption 'Size' ,'large value types out of row' ,0
TRUNCATE TABLE Size
INSERT INTO Size
SELECT 1, N'in row text'
UNION ALL
SELECT 2, N'' -- add here very large string
SELECT [ID], DATALENGTH([Text]) Size, LEN([Text]) [Len]
FROM [dbo].[Size]
EXEC sp_spaceused Size;
DROP TABLE Size
CREATE TABLE Size
(
[ID] TINYINT
,[Text] NVARCHAR(MAX)
)
EXEC sp_tableoption 'Size' ,'large value types out of row' ,1
TRUNCATE TABLE Size
INSERT INTO Size
SELECT 1, N'in row text'
UNION ALL
SELECT 2, N'' -- add here very large string
SELECT [ID], DATALENGTH([Text]) Size, LEN([Text]) [Len]
FROM [dbo].[Size]
EXEC sp_spaceused Size;
Run Code Online (Sandbox Code Playgroud)
并得到以下结果:

因此,似乎第一行现在占用了更多空间(正好是 8 KB)。因此,我再添加一行并再次进行测试:
INSERT INTO Size
SELECT 1, N'in row text'
UNION ALL
SELECT 1, N'in row text'
UNION ALL
SELECT 2, N'' -- add here very large string
Run Code Online (Sandbox Code Playgroud)
结果是一样的。因此,每行至少占用 8 KB 是不正确的,但实际上增加了大小。我知道:
表中的 varchar(max)、nvarchar(max)、varbinary(max)、xml 和大型用户定义类型 (UDT) 列存储在行外,具有指向根的 16 字节指针。
但是在这种情况下可以忽略这个 16 字节的指针。
small如果选项为真,谁能告诉有没有办法确定将花费多少空间开销值?
我打算将此选项应用于大表并想计算表大小将如何受到影响。
请注意,我知道该值仅out of the row在插入或更新时才会移动。
小智 5
如果你使用
DBCC IND('TestDb', 'Size', -1)
Run Code Online (Sandbox Code Playgroud)
您可以获得 LOB 页面的文件和页码(其中保存了“行外”值)
现在,使用该信息获取页面的转储:
DBCC PAGE('TestDb', 3, 938947, 1) WITH TABLERESULTS;
Run Code Online (Sandbox Code Playgroud)

从这些结果我可以看到,对于 64 字节或更少的字符串,记录大小将始终为 84 字节。对于更长的字符串将是实际字节加上 14 个字节(我没有分析比页面长的字符串)并且存储引擎将尝试在 LOB 页面中容纳尽可能多的这些记录。