Eu tenho uma tabela de cerca de 350m de linhas em um servidor vinculado no qual adicionei uma coluna INT adicional para servir como uma contagem (external_identification) de registros como resultado de uma junção em PACKAGE e DOC2. Como as tabelas são muito grandes, gostaria de processar a atualização em lotes, para poder avaliar o progresso e evitar a criação de tabelas temporárias enormes. Cada coluna é indexada.
Este seria um bom exemplo em que um CTE entra em jogo? Honestamente, eles me confundem com a maneira como precisam ser escritos, é difícil de visualizar...
As tabelas são estruturadas como:
ServerA (servidor SQL utilitário)
Tabela: CLIP_IDs
Colunas: Package_UUID nvarchar(255), MessageExtractState tinyint, [count] int (350m linhas)
ServerB (principal servidor de banco de dados)
Tabela: PACKAGE
Colunas: Package_UUID nvarchar(255), Package_id bigint (650m linhas)
Tabela: DOC2
Colunas: External_Identification nvarchar(255), Package_id bigint (2b linhas)
Ambos os servidores SQL estão vinculados nos dois sentidos, se iniciar a consulta de um for mais eficiente. Tenho a sensação de que emitir a consulta do ServerA será, pois parece que o plano de execução oferece menos consultas remotas.
Interrompi a consulta abaixo após 26 horas porque acho que tenho um erro de lógica de sintaxe . Alguém pode explicar o que é e oferecer alguma sugestão, por favor?
Executado do ServidorA:
DECLARE @rowsUpdated INT
SET @rowsUpdated = 1
WHILE (@rowsUpdated > 0)
BEGIN
UPDATE CLIP_IDs
SET [Count] = x.[count]
FROM (
SELECT TOP 50000 c.package_uuid
,count(d.external_identification) AS [count]
FROM CLIP_IDs c
INNER JOIN ServerB.DATABASE.dbo.package p(NOLOCK) ON c.package_uuid = p.package_uuid
INNER JOIN ServerB.DATABASE.dbo.doc2 d(NOLOCK) ON p.package_id = d.package_id
WHERE c.messageextractstate = 1
AND c.[count] IS NULL
GROUP BY c.package_uuid
) x
SET @rowsUpdated = @@rowcount
PRINT N'Finished set of rows: ' + convert(VARCHAR, getdate(), 120)
END
Dependendo de suas permissões, o servidor vinculado pode estar tentando transmitir todos os dados localmente e, em seguida, fazer a filtragem. Referências
Você pode pular essa dor calculando a contagem agregada total primeiro em uma tabela no servidor local e depois superá-la.
Tente executar essa consulta localmente no ServerB primeiro para entender a taxa de transferência teórica sem considerar sua rede. Você pode fazer algumas estimativas rápidas e sujas com base nos tamanhos dos dados (500 + 8 por linha na tabela temporária) e, em seguida, depende da sua rede. Espero que tudo isso seja rede local.
Se o tempo for significativamente diferente entre a execução no ServerB e o retorno, talvez seja necessário usar a sintaxe OPENQUERY para forçar a junção no servidor remoto. Código aproximadamente