program story

varchar (max) 변수의 최대 크기

inputbox 2020. 9. 17. 07:51
반응형

varchar (max) 변수의 최대 크기


과거에 누군가가 .NET의 최대 크기를 물었다 varchar(max)면 2GB라고 말했거나 더 정확한 수치 (2 ^ 31-1 또는 2147483647)를 찾아봤을 것 입니다.

그러나 최근 테스트에서 varchar(max)변수가이 크기를 분명히 초과 할 수 있음을 발견했습니다 .

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)

이제 변수 가 2GB 장벽을 초과 할 수 있다는 것을 알고 있다면 변수에 대한 실제 제한이 무엇인지 아는 사람이 varchar(max)있습니까?


(위의 테스트는 SQL Server 2008 (R2 아님)에서 완료되었습니다. 다른 버전에도 적용되는지 알고 싶습니다.)


내가 말할 수있는 한 2008 년에는 상한선이 없습니다.

SQL Server 2005에서 질문의 코드는 다음 @GGMMsg같은 변수 할당에 실패합니다.

허용되는 최대 크기 인 2,147,483,647 바이트를 초과하여 LOB를 늘리려 고합니다.

아래 코드는 실패합니다

REPLICATE : 결과 길이가 대상 대형 유형의 길이 제한 (2GB)을 초과합니다.

그러나 이러한 제한은 조용히 해제 된 것으로 보입니다. 2008 년

DECLARE @y VARCHAR(MAX) = REPLICATE(CAST('X' AS VARCHAR(MAX)),92681); 

SET @y = REPLICATE(@y,92681);

SELECT LEN(@y) 

보고

8589767761

32 비트 데스크톱 컴퓨터에서 실행 했으므로이 8GB 문자열은 주소 지정 가능한 메모리를 초과합니다.

달리는

select internal_objects_alloc_page_count
from sys.dm_db_task_space_usage
WHERE session_id = @@spid

반환 됨

internal_objects_alloc_page_co 
------------------------------ 
2144456    

그래서이 모든 것이 길이에 대한 유효성 검사없이 LOB페이지에 저장된다고 가정합니다 tempdb. 페이지 수 증가는 모두 SET @y = REPLICATE(@y,92681);문과 관련이 있습니다. 초기 변수 할당 @yLEN계산은 이것을 증가시키지 않았습니다.

The reason for mentioning this is because the page count is hugely more than I was expecting. Assuming an 8KB page then this works out at 16.36 GB which is obviously more or less double what would seem to be necessary. I speculate that this is likely due to the inefficiency of the string concatenation operation needing to copy the entire huge string and append a chunk on to the end rather than being able to add to the end of the existing string. Unfortunately at the moment the .WRITE method isn't supported for varchar(max) variables.

Addition

I've also tested the behaviour with concatenating nvarchar(max) + nvarchar(max) and nvarchar(max) + varchar(max). Both of these allow the 2GB limit to be exceeded. Trying to then store the results of this in a table then fails however with the error message Attempting to grow LOB beyond maximum allowed size of 2147483647 bytes. again. The script for that is below (may take a long time to run).

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

EDIT: After further investigation, my original assumption that this was an anomaly (bug?) of the declare @var datatype = value syntax is incorrect.

I modified your script for 2005 since that syntax is not supported, then tried the modified version on 2008. In 2005, I get the Attempting to grow LOB beyond maximum allowed size of 2147483647 bytes. error message. In 2008, the modified script is still successful.

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)

참고URL : https://stackoverflow.com/questions/7611394/maximum-size-of-a-varcharmax-variable

반응형