一个表中的每一行最多可以包含 8,060 字节。在 SQL Server 2008 中,对于包含 varchar、nvarchar、varbinary、sql_variant 或 CLR 用户定义类型列的表,可以放宽此限制。其中每列的长度仍必须在 8,000 字节的限制内,但是它们的总宽可以超过 8,060 字节的限制。创建和修改 varchar、nvarchar、varbinary、sql_variant 或 CLR 用户定义类型的列以及更新或插入数据时,此限制适用于上述列。
create table big(a char(4000),b char(4000),c char(4000))
Msg 1701, Level 16, State 1, Line 3
Creating or altering table 'big' failed because the minimum row size would be 12007, including 7 bytes of internal overhead. This exceeds the maximum allowable table row size of 8060 bytes.
解决办法就是把其中一个改成varchar,让他移动到 ROW_OVERFLOW_DATA 分配单元的另一页上。
create table big(a char(4000),b char(4000),c varchar(4000))
每列的长度还是受到8000的限制的:
1.创建表失败
create table TestBigTable (char1 varchar(8001) not null)
--消息 131,级别 15,状态 2,第 1 行
--赋予 列 'char1' 的大小(8001)超出了任意数据类型的最大允许值(8000)。
2.创建表插入数据都成功,但截断成8000了
create table TestBigTable (char1 varchar(max) not null)
--(1 行受影响)
insert TestBigTable (char1) select replicate('a',8004)
--(1 行受影响)
select LEN(char1) as len from TestBigTable
/*len
--------------------
8000
(1 行受影响)
*/
利用的“行溢出”功能,对于在特定情况下允许行长度大于 8,060 个字节效果很好,但却不适合大多数长度过大的行,而且可能使查询性能大打折扣,正如您所遇到的情况那样。
发生这种情况的原因是,当某行的长度开始变得过大时,该行中的其中一个可变长度列会被“推出行”。这意味着该列会在数据或索引页上从行中移到文本页中。至于原来列中的值,会由指针取代,指向该列中的值在数据文件中的新位置。
这与用来存储 XML、文本、图像或 varchar(max) 等常规 LOB(大型对象)列的机制完全相同。请注意,如果表架构包含多个可变长度列,就无法保证在多个行的长度变得过大时推出的会是同一列。
这种机制可能会产生性能问题。如果查询从一个表格行中检索的可变长度列已被推出该行,可能突然之间需要额外的 I/O 来读取内含行外位置的值的文本页。如果有多个行的长度过大,从多个行中检索相同的可变长度列的查询,可能产生无法预料的性能问题,严重程度取决于被推出行的值的数量。
在您遇到的情况中,对包含可变长度列的选择列表执行范围扫描或表扫描的查询,正是因行溢出及其影响而导致性能下降。这与索引是否执行过完全的碎片整理无关,当可变长度列被推出行时,因为必须使用随机 I/O 读取内含行外的值的文本页,所以之前有效的扫描作业已基本中断。
虽然行溢出在特定的情况下对于长度过大的行仍然很有用,但如果查询的性能至关重要,则不应该在您的设计里面过度利用。
http://blogs.msdn.com/chadboyd/archive/2007/02/24/row-sizes-exceeding-8060-bytes-in-sql-2005.aspx
2万+

被折叠的 条评论
为什么被折叠?



