Exporter de gros résultats SQL sans saturer le client
Limitez la mémoire du client, analysez ASYNC_NETWORK_IO et séparez extraction SQL et téléchargement lent avec une preuve de complétude.
Une requête de plusieurs millions de lignes n'est pas terminée pour l'utilisateur lorsque SQL Server trouve la première. Il reste à transférer, décoder, formater, écrire et livrer les données. Un plan rapide peut accompagner un export lent et un processus applicatif à court de mémoire.
Mesurer le chemin complet
Relevez délai de première ligne, fin de lecture, fin d'écriture, nombre de lignes, octets produits et pic mémoire. Ces mesures séparent calcul serveur, transfert et formatage. Chronométrer uniquement le premier Read ne mesure pas l'export entier.
Pendant une exécution lente, cette requête en lecture seule observe les demandes actives avec les permissions serveur adaptées.
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;
Des observations répétées de ASYNC_NETWORK_IO indiquent une attente liée à la consommation des résultats ou au progrès réseau. Elles ne prouvent pas une panne réseau. Un client qui compresse, journalise ou appelle une API après chaque ligne peut lire trop lentement. Comparez CPU client, débit du support de sortie et données réseau.
Réduisez les données inutiles à la source. Sélectionnez les colonnes requises et appliquez les filtres ou agrégations valides en SQL. Une description volumineuse jetée ensuite coûte tout de même transfert et décodage. Préservez le besoin : remplacer un export détaillé par des totaux change le produit.
Borner la mémoire et comprendre la contrepartie
Un lecteur vers l'avant évite de construire une collection complète. Pour de grandes colonnes binaires ou textuelles, SequentialAccess et les API de flux SqlClient permettent une lecture progressive. Respectez l'ordre d'accès aux colonnes et terminez la consommation d'une valeur avant les champs suivants selon ce mode.
L'asynchronisme ne limite pas automatiquement la mémoire. Créer une tâche par ligne et conserver toutes les tâches ou lignes fait toujours croître le processus. Utilisez un canal borné ou des lots limités entre extraction et transformation, avec un nombre fixe de workers.
Lorsque la sortie ralentit, le tampon doit cesser de grandir. Cette régulation conserve toutefois lecteur et connexion ouverts. Selon la requête et l'isolation, la durée peut prolonger des verrous, retenir des versions ou occuper une allocation mémoire. Tout charger d'abord libère le lecteur plus tôt, mais transfère la pression vers le client.
Pour un téléchargement utilisateur lent, un job de fond peut produire un fichier temporaire dans un stockage contrôlé et fermer le lecteur avant sa livraison. Rendez le fichier final disponible seulement après réussite, avec nombre de lignes, taille et éventuellement empreinte. Un fichier interrompu ne doit pas être présenté comme complet.
Définir cohérence et fin réelle
Décidez du moment que représente l'export. Plusieurs blocs indépendants en read committed ne constituent pas automatiquement un instantané cohérent. Les lignes peuvent changer entre blocs. Une longue transaction snapshot offre d'autres garanties, mais retient potentiellement des versions. Documentez ce contrat et mesurez son coût.
Une sortie déterministe ou reprenable nécessite un ordre stable. ORDER BY peut ajouter du travail serveur et doit faire partie des tests. Une borne supérieure de clé ne garantit pas que les valeurs des lignes restent identiques pendant l'extraction.
Propagez l'annulation et libérez lecteur, commande et connexion possédée sur chaque sortie. Terminez explicitement la transaction du job. Testez un consommateur déconnecté à mi-parcours, un disque plein, une conversion tardive en erreur et la reprise de la même demande.
Enfin, distinguez job terminé et téléchargement réussi. Un fichier valide peut exister malgré la perte de connexion du navigateur. Le réutiliser coûte souvent moins et évite une nouvelle extraction. Un export fiable possède des ressources bornées et un signal de complétude explicite, pas seulement une boucle qui finit par ne plus recevoir de lignes.
Références techniques: Microsoft Learn: ASYNC_NETWORK_IO · Microsoft Learn: SqlClient streaming.