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

Constructeur de valeur de table Limite maximale de lignes dans Select

Il n'y a pas de limite codée en dur pertinente (65 536 * la taille du paquet réseau de 4 Ko est de 268 Mo et la longueur de votre script est loin de cela), bien qu'il soit déconseillé d'utiliser cette méthode pour un grand nombre de lignes.

L'erreur que vous voyez est générée par les outils clients et non par SQL Server. Si vous construisez la chaîne SQL en SQL dynamique, la compilation peut au moins démarrer avec succès

DECLARE @SQL NVARCHAR(MAX) = '(100,200,300),
';

SELECT @SQL = 'SELECT * FROM (VALUES ' + REPLICATE(@SQL, 1000000) + '
(100,200,300)) tc (proj_d, period_sid, val)';

SELECT @SQL AS [processing-instruction(x)]
FOR XML PATH('')

SELECT DATALENGTH(@SQL) / 1048576.0 AS [Length in MB] --30.517705917

EXEC(@SQL);

Bien que j'aie tué ce qui précède après environ 30 minutes de temps de compilation et qu'il n'ait toujours pas produit de ligne. Les valeurs littérales doivent être stockées dans le plan lui-même sous forme de tableau de constantes et SQL Server dépense beaucoup de temps essayer de dériver des propriétés à leur sujet aussi.

SSMS est une application 32 bits et lance un std::bad_alloc exception lors de l'analyse du lot

Il essaie de pousser un élément sur un vecteur de Token qui a atteint sa capacité et sa tentative de redimensionnement échoue en raison de l'indisponibilité d'une zone de mémoire contiguë suffisamment grande. Ainsi, la déclaration n'arrive même jamais jusqu'au serveur.

La capacité vectorielle augmente de 50 % à chaque fois (c'est-à-dire en suivant la séquence ici ). La capacité dont le vecteur a besoin pour croître dépend de la façon dont le code est agencé.

Les besoins suivants doivent passer d'une capacité de 19 à 28.

SELECT * FROM (VALUES (100,200,300),(100,200,300),(100,200,300),(100,200,300),(100,200,300),(100,200,300)) tc (proj_d, period_sid, val)

et ce qui suit n'a besoin que d'une taille de 2

SELECT * FROM (VALUES (100,200,300),(100,200,300),(100,200,300),(100,200,300),(100,200,300),(100,200,300)) tc (proj_d, period_sid, val)

Ce qui suit a besoin d'une capacité de> 63 et <=94.

SELECT *
FROM   (VALUES 
      (100,
       200,
       300),
      (100,
       200,
       300),
      (100,
       200,
       300),
      (100,
       200,
       300),
      (100,
       200,
       300),
      (100,
       200,
       300)
       ) tc (proj_d, period_sid, val) 

Pour un million de lignes disposées comme dans le cas 1, la capacité vectorielle doit atteindre 3 543 306.

Vous constaterez peut-être que l'une ou l'autre des solutions suivantes permettra à l'analyse côté client de réussir.

  1. Réduire le nombre de sauts de ligne.
  2. Redémarrage de SSMS dans l'espoir que la demande de grande mémoire contiguë réussisse lorsqu'il y a moins de fragmentation de l'espace d'adressage.

Cependant, même si vous réussissez à l'envoyer au serveur, cela finira par tuer le serveur lors de la génération du plan d'exécution de toute façon, comme indiqué ci-dessus.

Vous ferez bien mieux d'utiliser l'assistant d'importation et d'exportation pour charger la table. Si vous devez le faire dans TSQL, vous constaterez que le diviser en lots plus petits et/ou en utilisant une autre méthode telle que le déchiquetage XML fonctionnera mieux que les constructeurs à valeur de table. Ce qui suit s'exécute en 13 secondes sur ma machine par exemple (bien que si vous utilisez SSMS, vous devrez probablement diviser en plusieurs lots plutôt que de coller une chaîne littérale XML massive).

DECLARE @S NVARCHAR(MAX) = '<x proj_d="100" period_sid="200" val="300" />
' ; 

DECLARE @Xml XML = REPLICATE(@S,1000000);

SELECT 
    x.value('@proj_d','int'),
    x.value('@period_sid','int'),
    x.value('@val','int')
FROM @Xml.nodes('/x') c(x)