Sql server 寻找行溢出数据发生的精确性

Sql server 寻找行溢出数据发生的精确性,sql-server,sql-server-2005,database-design,optimization,normalization,Sql Server,Sql Server 2005,Database Design,Optimization,Normalization,我目前正处于为我们的CRM应用程序中的一个大型模块计划重写的初始阶段 我目前正在研究的一个领域是数据库优化,我还没有做出任何决定,但我只是想确保我正确理解行溢出数据的概念- 我们使用的是SQLServer2005,据我所知,行大小限制为8060字节,之后将发生溢出 我运行了一个查询,以获取特定读密集型数据库的最大行大小 SELECT OBJECT_NAME (sc.[id]) tablename , COUNT (1) nr_columns , SUM (sc.length) maxrowlen

我目前正处于为我们的CRM应用程序中的一个大型模块计划重写的初始阶段

我目前正在研究的一个领域是数据库优化,我还没有做出任何决定,但我只是想确保我正确理解行溢出数据的概念-

我们使用的是SQLServer2005,据我所知,行大小限制为8060字节,之后将发生溢出

我运行了一个查询,以获取特定读密集型数据库的最大行大小

SELECT OBJECT_NAME (sc.[id]) tablename
, COUNT (1) nr_columns
, SUM (sc.length) maxrowlength
FROM syscolumns sc
join sysobjects so
on sc.[id] = so.[id]
WHERE so.xtype = 'U'
GROUP BY OBJECT_NAME (sc.[id])
ORDER BY SUM (sc.length) desc
这给了我一些maxrowlength略高于8000但低于10000的桌子。另一个查询显示,平均行大小实际上非常小,大约1000字节

我的问题是:行溢出数据是基于每行还是基于每列?一旦8060字节的限制被扩展,导致其溢出的整个列是否会移动到另一页,或者只是特定的行

例如,给出以下简化模式:

col1 (int) | col 2 (varchar (4000)) | col 3(varchar(5000))
    1      |    4000 characters   |    5000 characters ***This row is overflowing
    2      |    4000 characters   |    100 characters
    3      |    150 characters    |    150 characters
    4      |    500 characters    |    600 characters
第1行到第4行的第3列的每一个字符都会被24字节指针替换,还是只替换为rowid1

我想知道,如果每一行都有一个指针,那么修复它就变得很重要,如果只有几行,也许我们可以承受性能上的打击


此外,我看到许多博客建议将可为NULL的列移到数据库的末尾,这样,如果值实际上为NULL,它们就不会占用任何行空间。这是真的吗?我们倾向于在末尾保留时间戳和跟踪列,因为这样更容易可视化。现在我想知道是否我们不应该将它们进一步向上移动,因为它们从来都不是空的。

只有当某一行溢出时,该行的违规数据才会被移动到单独的溢出页中-想象一下,如果仅仅因为一列中的一个值溢出而需要重建整个表,那会是多么令人头痛的事情


我还没有听说过将可空值移到表的末尾的想法-我必须检查一下

只有当某一行溢出时,该行的违规数据才会被移动到单独的溢出页中——想象一下,如果仅仅因为一列中的一个值溢出而需要重建整个表,那会是多么令人头痛


我还没有听说过将可空值移到表的末尾的想法-我必须检查一下

如果你有一行(比如1亿行)溢出,你会移动整列吗?没有

作为参考,保罗·兰德尔(Paul Randal)写了一篇文章,他是这个东西的神(我的黑体字)

您正在使用的“行溢出”功能非常适合于允许偶尔的行长度超过8060字节,但它不适合大多数行过大,并可能导致查询性能下降,正如您所经历的那样

原因是,当一行即将变得过大时,该行中的一个可变长度列将被推到“行外”。这意味着该列将从数据或索引页上的行中提取,并移动到文本页。替代旧列值的是一个指针,该指针指向数据文件中列值的新位置

和(我的粗体)

行溢出数据分配单元

对于表(堆或聚集表)、索引或索引视图使用的每个分区,都有一个行溢出数据分配单元。此分配单元包含零(0)个页面,直到in_row_数据分配单元中具有可变长度列(varchar、nvarchar、varbinary或sql_variant)的数据行超过8 KB行大小限制。当达到大小限制时,SQL Server会将宽度最大的列从该行移动到数据分配单元中的某一页。指向该行外数据的24字节指针保留在原始页面上


对于可为空的列,这是错误的。不管表定义中的列顺序如何,可为空的列都存储在磁盘结构的末尾。再给我一封信。任何以前的答案

如果你有一行(比如1亿行)溢出,你会移动整列吗?没有

作为参考,保罗·兰德尔(Paul Randal)写了一篇文章,他是这个东西的神(我的黑体字)

您正在使用的“行溢出”功能非常适合于允许偶尔的行长度超过8060字节,但它不适合大多数行过大,并可能导致查询性能下降,正如您所经历的那样

原因是,当一行即将变得过大时,该行中的一个可变长度列将被推到“行外”。这意味着该列将从数据或索引页上的行中提取,并移动到文本页。替代旧列值的是一个指针,该指针指向数据文件中列值的新位置

和(我的粗体)

行溢出数据分配单元

对于表(堆或聚集表)、索引或索引视图使用的每个分区,都有一个行溢出数据分配单元。此分配单元包含零(0)个页面,直到in_row_数据分配单元中具有可变长度列(varchar、nvarchar、varbinary或sql_variant)的数据行超过8 KB行大小限制。当达到大小限制时,SQL Server会将宽度最大的列从该行移动到数据分配单元中的某一页。指向该行外数据的24字节指针保留在原始页面上

对于可为空的列,这是错误的。不管表定义中的列顺序如何,可为空的列都存储在磁盘结构的末尾。再给我一封信。任何以前的答案

Null
点仅适用于可变长度列,并且最终只在列偏移量中保存2个字节