SQL Server na prática

Exportar grandes resultados SQL sem esgotar o cliente

Limite memória, investigue ASYNC_NETWORK_IO e separe extração SQL de downloads lentos com regras claras de consistência e conclusão.

Uma consulta com milhões de linhas não termina para o usuário quando o SQL Server encontra a primeira. Ainda é necessário transferir, decodificar, formatar, gravar e entregar os dados. Um plano rápido pode coexistir com exportação lenta e aplicação sem memória.

Medir o caminho completo

Registre tempo até a primeira linha, fim da leitura, fim da escrita, quantidade de linhas, bytes e pico de memória. Isso separa cálculo do servidor, transferência e formatação. Cronometrar apenas o primeiro Read não mede o export completo.

Durante uma execução lenta, esta consulta de leitura observa requisições ativas com as permissões de diagnóstico adequadas.

SELECT
    r.session_id, r.request_id,
    r.status, r.wait_type, r.wait_time,
    r.total_elapsed_time, r.cpu_time,
    r.logical_reads, r.reads, r.row_count,
    s.program_name, s.host_name
FROM sys.dm_exec_requests AS r
JOIN sys.dm_exec_sessions AS s ON s.session_id = r.session_id
WHERE s.is_user_process = 1
  AND r.session_id <> @@SPID
ORDER BY r.total_elapsed_time DESC;

ASYNC_NETWORK_IO recorrente indica espera ligada ao consumo dos resultados ou ao progresso da rede. Não comprova automaticamente uma rede defeituosa. Um cliente que comprime, grava logs ou faz uma chamada HTTP por linha pode ler lentamente. Compare CPU cliente, vazão da saída e evidências de rede.

Reduza dados desnecessários na origem. Selecione as colunas necessárias e aplique filtros ou agregações válidas no SQL. Exportar uma descrição enorme para descartá-la depois gasta transferência e decodificação. Preserve a semântica: substituir detalhes por totais muda o resultado solicitado.

Limitar memória e entender a contrapressão

Um reader somente para frente evita construir uma coleção contendo tudo. Para grandes colunas binárias ou textuais, SequentialAccess e as APIs de streams do SqlClient permitem leitura incremental. Respeite a ordem das colunas e conclua o consumo de um valor antes de avançar conforme esse padrão.

E/S assíncrona não limita memória sozinha. Criar uma tarefa por linha e guardar todas as tarefas ou linhas continua crescendo com o volume. Use um canal limitado ou lotes fixos entre extração e transformação, com quantidade controlada de workers.

Quando a próxima etapa fica lenta, o buffer precisa parar de crescer. Essa contrapressão mantém reader e conexão abertos. Conforme consulta e isolamento, execução prolongada pode estender locks, reter versões ou ocupar uma concessão de memória. Ler tudo primeiro libera o reader antes, mas transfere pressão para o cliente.

Para downloads lentos, um job de fundo pode gravar um arquivo temporário em armazenamento controlado e fechar o reader antes da entrega. Disponibilize o arquivo final apenas depois de sucesso, com linhas, tamanho e preferencialmente checksum. Um arquivo interrompido não deve aparecer como completo.

Definir consistência e conclusão

Decida qual momento o export representa. Várias partes independentes em read committed não formam automaticamente um snapshot coerente. Linhas podem mudar entre partes. Uma transação snapshot longa oferece outra semântica, mas pode reter versões. Documente o contrato e meça seu custo.

Use ordenação estável quando o arquivo precisa ser determinístico ou retomável. ORDER BY pode acrescentar trabalho ao servidor e deve entrar nos testes. Um limite superior de chave não garante que os valores permaneçam iguais durante a extração.

Propague cancelamento e descarte reader, comando e conexão própria em todo caminho de saída. Termine explicitamente a transação do job. Teste consumidor desconectado no meio, disco cheio, conversão inválida após muitas linhas e repetição da mesma solicitação.

Por fim, diferencie job concluído de download bem-sucedido. Um arquivo válido pode existir mesmo após perder a conexão do usuário. Reutilizá-lo costuma ser mais seguro e barato que consultar novamente. Um export confiável combina recursos limitados e sinal explícito de completude, em vez de depender apenas de um loop que eventualmente para de receber linhas.

Referências técnicas: Microsoft Learn: ASYNC_NETWORK_IO · Microsoft Learn: SqlClient streaming.

Pergunte sobre este artigo

Tem alguma dúvida sobre este tema?

Conte o que você está avaliando ou onde encontrou dificuldades. Responderemos com uma recomendação prática.

Inquiries are not enabled in this preview.

Fazer uma pergunta sobre este artigo