jfr*_*how 1 sql-server optimization database-design sql-server-2005 normalization
我目前正处于为CRM应用程序中的大型模块重写计划的初始阶段.
我目前正在研究的一个领域是数据库优化,我还没有做出任何决定,但我只是想确保我理解ROW_OVERFLOW_DATA的概念 - http://msdn.microsoft.com/en-us/library/ ms186981.aspx
我们正在使用SQL Server 2005,我的理解是行大小限制是8,060字节,之后会发生溢出.
我运行了一个查询来获取特定读取密集型数据库的最大行大小
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
Run Code Online (Sandbox Code Playgroud)
这给了我一些表格,其最大长度略高于8,000,但低于10,000.另一个查询显示平均行大小实际上非常小,大约1,000字节.
我的问题是:基于每一行是ROW_OVERFLOW_DATA还是每列?一旦扩展了8,060字节的限制,导致它溢出的整个列移动到另一个页面,还是只有特定的行?
因此,例如给出以下简化模式:
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
Run Code Online (Sandbox Code Playgroud)
第1行到第4行的第3列是否会被24字节指针或只有rowID 1取代?
我想知道是因为如果它的每一行都有一个指针,那么修复它就变得很重要,如果它只有几行,我们就可以获得性能.
此外,我已经看到许多博客建议将可空列移到数据库的末尾,这样如果值实际上是NULL,则它们不占用任何行空间.这是真的?我们倾向于将时间戳和跟踪列保留在最后,因为它更容易可视化.现在我想知道是否我们不应该进一步向上移动,因为它们永远不会为NULL.
如果你有一行,比如一个1亿溢出,你会移动整列吗?没有.
作为参考,来自Paul Randal的一篇Technet文章是这个东西的上帝(我的大胆)
您正在使用,行溢出的功能,是伟大的,允许偶尔排长于8,060字节,但它不是非常适合于广大行是放大,并可能导致查询性能下降,因为你是经历.
这样做的原因是,当一个行即将成为过大的,可变长度列中的一个行中的推"行外".这意味着该列取自数据或索引页面上的行并移动到文本页面.代替旧列值,替换指针指向数据文件中列值的新位置.
和MSDN(我的大胆)
ROW_OVERFLOW_DATA分配单位
对于表(堆或聚簇表),索引或索引视图使用的每个分区,都有一个ROW_OVERFLOW_DATA分配单元.此分配单元包含零(0)页,直到IN_ROW_DATA分配单元中具有可变长度列(varchar,nvarchar,varbinary或sql_variant)的数据行超过8 KB行大小限制.达到大小限制时,SQL Server将具有该行最大宽度的列移动到ROW_OVERFLOW_DATA分配单元中的页面.在原始页面上保留了一个指向该行外数据的24字节指针.
至于你的NULLable列,这是错误的.无论列表顺序中的列顺序如何,都可以将NULLable列存储在磁盘结构的末尾.Paul Randal的参考文献:存储引擎内部:再次对记录进行解剖.我在这里的任何一些先前的答案在SO
| 归档时间: |
|
| 查看次数: |
1074 次 |
| 最近记录: |