varchar (max) 변수의 최대 크기


89

과거에 누군가 나에게 .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 아님)에서 완료되었습니다. 다른 버전에도 적용되는지 알고 싶습니다.)


declare @x varchar(max) = 'XX'; SELECT LEN(REPLICATE(@x,2147483647))주는 4294967294나를 위해하지만 실행하는 데 시간이 오래 소요 - (가) 후에도 SELECT그렇게하지 않도록 여분의 시간이 일 소요되는 것을 반환했습니다.
Martin Smith

답변:


74

내가 말할 수있는 한 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계산은 이것을 증가시키지 않았습니다.

이것을 언급하는 이유는 페이지 수가 내가 예상했던 것보다 훨씬 많기 때문입니다. 8KB 페이지를 가정하면 16.36GB에서 작동하며 이는 분명히 필요한 것보다 두 배 더 많거나 적습니다. 나는 이것이 기존 문자열의 끝에 추가 할 수있는 것이 아니라 전체 거대한 문자열을 복사하고 끝에 청크를 추가해야하는 문자열 연결 작업의 비 효율성 때문이라고 추측합니다. 불행히도 현재이 .WRITE메서드 varchar (max) 변수에 대해 지원되지 않습니다 .

부가

또한 연결 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

1
우수-문서가 "불완전"한 것처럼 보입니다. 일반적인 페이지는 최대 "저장 크기"를 참조하며, 이는 아마도 변수가 아닌 열에 만 적용됩니다.
Damien_The_Unbeliever

@Damien-확실히 그렇게 나타납니다. 총 페이지 수 측면에서 도달 할 수있는 다른 제한이 있는지는 확실하지 않지만 이것이 B 트리 구조 (SQL Server 2008 내부의 p.381 기준)에 저장되어 있으므로 원칙적으로 확실히 확장 할 수 있다고 생각합니다.
Martin Smith

@Damien_The_Unbeliever- 여기의 문서는 여기 의 실험을 기반으로하여 완전히 잘못된 것처럼 보입니다. "대형 개체 (LOB) 데이터 유형 변수 및 매개 변수 ... 유형의 크기는 최대 2GB 일 수 있습니다."
Martin Smith

쓸모 없지만 흥미 롭습니다. 이론적으로 디스크를 하나의 변수로 채울 수 있습니다 ... :-)
gbn

변수에 값을 저장하는 것이 열에 저장하는 것과 같지 않기 때문에 여기서 약간 망설입니다. 대신 열로 이것을 시도하고 싶습니까? 아니면 업데이트가 있습니까? SQL Server 2000조차도 varchar변수 나 varchar열에 넣지 않는 한 코드의 리터럴 문자열에 8000 자보다 긴 값을 가질 수 있습니다 .
ErikE jul.

9

편집 : 추가 조사 후 이것이 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)

스크립트는 항상 테이블 삽입을 시도하여 오류를 생성하지만 2008 년에는 항상 첫 번째 결과 집합에 하나의 결과가 표시되어 변수가 존재하고 길이가 2 ^ 31-1보다 깁니다.
Damien_The_Unbeliever 2014 년

@Damien_The_Unbeliever : 스크립트를 변수 부분으로 잘라 냈고 이제 동일한 결과를 얻었습니다. 2005 년 Attempting to grow...set @GGMMsg=...성명서에 오류가 발생했습니다 . 2008 년 스크립트는 성공적입니다.
Joe Stefanelli 2011 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.