Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Taille maximale d'une variable varchar(max)

Autant que je sache, il n'y a pas de limite supérieure en 2008.

Dans SQL Server 2005, le code de votre question échoue lors de l'affectation au @GGMMsg variables avec

Tentative d'extension de LOB au-delà de la taille maximale autorisée de 2 147 483 647 octets.

le code ci-dessous échoue avec

REPLICATE :la longueur du résultat dépasse la limite de longueur (2 Go) du grand type cible.

Cependant, il semble que ces limitations aient été discrètement levées. En 2008

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

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

SELECT LEN(@y) 

Retours

8589767761

J'ai exécuté ceci sur mon ordinateur de bureau 32 bits, donc cette chaîne de 8 Go dépasse largement la mémoire adressable

En cours d'exécution

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

Renvoyé

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

donc je suppose que tout cela est simplement stocké dans LOB pages dans tempdb sans validation sur la longueur. La croissance du nombre de pages était entièrement associée au SET @y = REPLICATE(@y,92681); déclaration. L'affectation initiale de la variable à @y et le LEN le calcul n'a pas augmenté cela.

La raison de mentionner cela est que le nombre de pages est beaucoup plus élevé que ce à quoi je m'attendais. En supposant une page de 8 Ko, cela correspond à 16,36 Go, ce qui est évidemment plus ou moins le double de ce qui semble être nécessaire. Je suppose que cela est probablement dû à l'inefficacité de l'opération de concaténation de chaînes qui nécessite de copier l'intégralité de la chaîne énorme et d'ajouter un morceau à la fin plutôt que de pouvoir ajouter à la fin de la chaîne existante. Malheureusement pour le moment le .WRITE la méthode n'est pas prise en charge pour les variables varchar(max).

Ajout

J'ai également testé le comportement en concaténant nvarchar(max) + nvarchar(max) et nvarchar(max) + varchar(max) . Les deux permettent de dépasser la limite de 2 Go. Essayer ensuite de stocker les résultats de ceci dans une table échoue cependant avec le message d'erreur Attempting to grow LOB beyond maximum allowed size of 2147483647 bytes. de nouveau. Le script pour cela est ci-dessous (peut prendre beaucoup de temps à s'exécuter).

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