varchar(max)variables的最大大小
在过去的任何时候,如果有人问我varchar(max)
的最大大小,我会说2GB,或者查找更准确的数字 (2 ^ 31-1或2147483647)。
但是,在最近的一些testing中,我发现varchar(max)
variables显然可以超过这个大小:
create table T ( Val1 varchar(max) not null ) go declare @KMsg varchar(max) = REPLICATE('a',1024); declare @MMsg varchar(max) = REPLICATE(@KMsg,1024); declare @GMsg varchar(max) = REPLICATE(@MMsg,1024); declare @GGMMsg varchar(max) = @GMsg + @GMsg + @MMsg; select LEN(@GGMMsg) insert into T(Val1) select @GGMMsg select LEN(Val1) from T
结果:
(no column name) 2148532224 (1 row(s) affected) Msg 7119, Level 16, State 1, Line 6 Attempting to grow LOB beyond maximum allowed size of 2147483647 bytes. The statement has been terminated. (no column name) (0 row(s) affected)
所以,鉴于我现在知道一个variables可以超过2GB的障碍 – 有没有人知道什么是一个varchar(max)
variables的实际限制?
(以上testing在SQL Server 2008上完成(不是R2),我想知道它是否适用于其他版本)
据我所知,2008年没有上限。
在SQL Server 2005中,您问题中的代码在使用@GGMMsg
variables时失败
试图增长LOB超出最大允许大小2,147,483,647字节。
下面的代码失败
REPLICATE:结果长度超过目标大型的长度限制(2GB)。
但是,似乎这些限制已经悄然解除。 在2008年
DECLARE @y VARCHAR(MAX) = REPLICATE(CAST('X' AS VARCHAR(MAX)),92681); SET @y = REPLICATE(@y,92681); SELECT LEN(@y)
返回
8589767761
我在32位桌面机器上运行这个8GBstring的方式超出了可寻址内存
运行
select internal_objects_alloc_page_count from sys.dm_db_task_space_usage WHERE session_id = @@spid
回
internal_objects_alloc_page_co ------------------------------ 2144456
所以我认为这一切都只是被存储在tempdb
中的LOB
页面上,没有长度validation。 页数增长都与SET @y = REPLICATE(@y,92681);
声明。 @y
的初始variables赋值和LEN
计算没有增加这个值。
提到这个的原因是因为页数比我预期的要多得多。 假设一个8KB的页面,那么这个16.36 GB的内存就显得多了或less一些,似乎是必要的。 我推测这可能是由于string连接操作的效率低下需要复制整个巨大的string,并追加一个块到最后,而不是能够添加到现有string的末尾。 不幸的是,目前.WRITE
方法不支持 varchar(max)variables。
加成
我还testing了连接nvarchar(max) + nvarchar(max)
和nvarchar(max) + varchar(max)
。 这两个都允许超过2GB的限制。 尝试将此结果存储在表中,然后失败,但是出现错误消息Attempting to grow LOB beyond maximum allowed size of 2147483647 bytes.
再次。 下面的脚本(可能需要很长时间才能运行)。
DECLARE @y1 VARCHAR(MAX) = REPLICATE(CAST('X' AS VARCHAR(MAX)),2147483647); SET @y1 = @y1 + @y1; SELECT LEN(@y1), DATALENGTH(@y1) /*4294967294, 4294967292*/ DECLARE @y2 NVARCHAR(MAX) = REPLICATE(CAST('X' AS NVARCHAR(MAX)),1073741823); SET @y2 = @y2 + @y2; SELECT LEN(@y2), DATALENGTH(@y2) /*2147483646, 4294967292*/ DECLARE @y3 NVARCHAR(MAX) = @y2 + @y1 SELECT LEN(@y3), DATALENGTH(@y3) /*6442450940, 12884901880*/ /*This attempt fails*/ SELECT @y1 y1, @y2 y2, @y3 y3 INTO Test
编辑 :经过进一步调查,我原来的假设,这是一个exception(bug?)的declare @var datatype = value
语法是不正确的。
我修改了2005的脚本,因为这个语法不被支持,于是在2008年尝试了修改后的版本。在2005年,我得到了Attempting to grow LOB beyond maximum allowed size of 2147483647 bytes.
错误信息。 2008年,修改后的脚本仍然成功。
declare @KMsg varchar(max); set @KMsg = REPLICATE('a',1024); declare @MMsg varchar(max); set @MMsg = REPLICATE(@KMsg,1024); declare @GMsg varchar(max); set @GMsg = REPLICATE(@MMsg,1024); declare @GGMMsg varchar(max); set @GGMMsg = @GMsg + @GMsg + @MMsg; select LEN(@GGMMsg)