Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Limite máximo de linhas do construtor com valor de tabela em Select


Não há limite codificado relevante (65.536 * Tamanho do pacote de rede de 4 KB é 268 MB e o comprimento do script não chega nem perto disso), embora seja desaconselhável usar esse método para uma grande quantidade de linhas.

O erro que você está vendo é gerado pelas ferramentas do cliente, não pelo SQL Server. Se você construir o SQL String na compilação SQL dinâmica é capaz de pelo menos iniciar com sucesso
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);

Embora eu tenha matado o acima após ~ 30 minutos de tempo de compilação e ainda não tenha produzido uma linha. Os valores literais precisam ser armazenados dentro do próprio plano como uma tabela de constantes e o SQL Server gasta muito tempo tentando derivar propriedades sobre eles também.

O SSMS é um aplicativo de 32 bits e lança um std::bad_alloc exceção ao analisar o lote



Ele tenta empurrar um elemento para um vetor de Token que atingiu a capacidade e sua tentativa de redimensionar falha devido à indisponibilidade de uma área contígua de memória grande o suficiente. Portanto, a declaração nunca chega ao servidor.

A capacidade do vetor cresce 50% a cada vez (ou seja, seguindo a sequência aqui ). A capacidade que o vetor precisa para crescer depende de como o código é definido.

O seguinte precisa crescer de uma capacidade de 19 para 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)

e o seguinte só precisa de um tamanho 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)

O seguinte precisa de uma capacidade de> 63 e <=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) 

Para um milhão de linhas dispostas como no caso 1, a capacidade do vetor precisa crescer para 3.543.306.

Você pode descobrir que qualquer um dos seguintes permitirá que a análise do lado do cliente seja bem-sucedida.
  1. Reduza o número de quebras de linha.
  2. Reiniciar o SSMS na esperança de que a solicitação de memória contígua grande seja bem-sucedida quando houver menos fragmentação do espaço de endereço.

No entanto, mesmo que você o envie com sucesso para o servidor, ele só acabará matando o servidor durante a geração do plano de execução, conforme discutido acima.

Será muito melhor usar o assistente de importação e exportação para carregar a tabela. Se você precisar fazer isso em TSQL, verá que dividi-lo em lotes menores e/ou usar outro método, como fragmentar XML, terá um desempenho melhor do que construtores com valor de tabela. O seguinte é executado em 13 segundos na minha máquina, por exemplo (embora, se estiver usando o SSMS, você ainda tenha que dividir em vários lotes em vez de colar um literal enorme de string XML).
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)