Ответ 1
Насколько я могу судить, в 2008 году нет верхнего предела.
В SQL Server 2005 код в вашем вопросе терпит неудачу при назначении переменной @GGMMsg
с
Попытка увеличить LOB за максимальным разрешенным размером 2 147 483 647 байтов.
код ниже с ошибкой
REPLICATE: длина результата превышает предел длины (2 ГБ) целевой большой тип.
Однако, похоже, эти ограничения были спокойно сняты. В 2008 году
DECLARE @y VARCHAR(MAX) = REPLICATE(CAST('X' AS VARCHAR(MAX)),92681);
SET @y = REPLICATE(@y,92681);
SELECT LEN(@y)
Возвращает
8589767761
Я запустил это на своем 32-битном настольном компьютере, так что эта строка 8 Гбайт превосходит адресную память
Выполнение
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);
. Начальное присваивание переменной @y
и вычисление LEN
не увеличили это.
Причиной упоминания этого является то, что количество страниц намного больше, чем я ожидал. Предположим, что страница на 8 Кбайт тогда работает на уровне 16,36 ГБ, что, очевидно, более или менее удваивает то, что казалось бы необходимым. Я предполагаю, что это, вероятно, связано с неэффективностью операции конкатенации строк, необходимой для копирования всей огромной строки и добавления фрагмента в конец, а не для возможности добавления в конец существующей строки. К сожалению, в настоящий момент метод .WRITE
не поддерживается для переменных varchar (max).
Добавление
Я также проверил поведение с конкатенацией nvarchar(max) + nvarchar(max)
и nvarchar(max) + varchar(max)
. Оба из них позволяют превышать лимит 2 ГБ. Попытка затем сохранить результаты этого в таблице, а затем снова с сообщением об ошибке Attempting to grow LOB beyond maximum allowed size of 2147483647 bytes.
. script для этого ниже (может занять много времени).
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