2011-09-30 5 views
76

언제든지 이전에 누군가가 최대 크기 인 varchar(max)을 요청한 경우 2GB를 말하거나 더 정확한 figure (2^31- 1 또는 2147483647).최대 varchar (최대) 변수의 크기

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 

결과 :

그러나, 최근의 테스트에서, 나는 varchar(max) 변수는 분명히이 크기 초과 할 수 있다는 것을 발견

(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) 변수 인 것을 아는 사람이 있습니까?


+0

'declare @x varchar (max) = 'XX'; SELECT LEN (REPLICATE (@ x, 2147483647))'나를 위해'4294967294'를 주지만,'SELECT'가 반환 된 후에도 그 여분의 시간이 무엇을하는지 확실히 모릅니다. –

답변

62

지금까지 내가 SQL 서버 질문의 코드가

는 시도로 @GGMMsg 변수에 할당 실패 2005 년에서 2008 년

의 상한이 없다 말할 수있는 최대 허용 크기 인 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) 

반환 내 32 비트 데스크탑 컴퓨터에서이 작업을 실행

8589767761 

그래서이 8 기가 바이트 문자열

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

반환을 실행 주소 지정 가능 메모리

를 초과하는 방법입니다

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

그래서이 모든 내용은 길이가 유효하지 않은 tempdbLOB 페이지에 저장되어 있다고 가정합니다. 페이지 수 증가율은 모두 SET @y = REPLICATE(@y,92681); 성명과 관련이 있습니다. @yLEN으로 초기 변수를 지정해도 증가하지 않았습니다.

이유는 페이지 수가 예상했던 것보다 훨씬 많기 때문입니다. 8KB 페이지를 가정하면 16.36GB에서 작동하며 이는 분명히 필요한 것보다 더 많거나 적은 두 배입니다. 나는 이것이 거대한 문자열 전체를 복사해야하고 기존 문자열의 끝 부분에 추가 할 수있는 것보다 끝 부분에 청크를 추가해야하는 문자열 연결 작업의 비효율 때문인 것으로 추측합니다. 불행히도 순간에 .WRITE 방법 isn't supported varchar (최대) 변수에 대한.

추가

는 또한 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 
+0

Excellent - 문서가 오히려 "불완전"한 것처럼 보일 것입니다. 보통 페이지는 최대 "저장 공간 크기"를 가리키며, 변수가 아닌 열에 만 적용됩니다. –

+0

@Damien - 확실히 그런 식으로 보입니다. 확실하지 않은 경우 총 페이지의 측면에서 도달 할 수있는 몇 가지 다른 한계가 있지만 나는 이것이 원칙적으로 확실히 확장 될 수있는 B 트리 구조 (SQL Server 2008 내부의 p.381을 기반으로)에 저장되어 있다고 생각합니다. –

+0

@Damien_The_Unbeliever - [여기에있는 문서] (http://msdn.microsoft.com/en-us/library/ms345368.aspx)는 여기 실험을 토대로 잘못 표시되는 것처럼 보입니다. "Large object (LOB) 데이터 유형 변수 및 매개 변수 ... 유형은 최대 2GB 크기가 될 수 있습니다. " –

9

편집 (. SQL 서버 2008 (안 R2)에 완료 시험 위에 나는 다른 버전에 적용되는지 여부를 알고 싶네) : 추가 조사 후, 내 원래의 가정을 그 이것은 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) 
+0

스크립트는 항상 (테이블 삽입을 시도하여) 오류를 생성하지만, 2008 년에는 변수가 존재하고 길이가 2^31-1보다 긴 첫 번째 결과 집합에서 항상 하나의 결과를 얻습니다 . –

+0

@Damien_The_Unbeliever : 스크립트를 가변 부분으로 잘라 내고 이제는 당신과 같은 결과를 얻습니다. 2005 년에,'set @GGMMsg = ...'문에서'Attempting to grow ... '오류가 발생했습니다. 2008 년 스크립트는 성공적입니다. –