Queries can finish in milliseconds and still take minutes to reach a laptop across a VPN. The server produces rows into buffers, the connection carries them, and the client consumes them, and those stages overlap rather than run in sequence. Any of them can become the limit. Find the stage that is actually waiting before you change bandwidth or enable compression.

Three Stages, One Stopwatch

Separate the timer into two numbers that mean different things: the moment the first row is available and the moment the last row has been consumed. A grid that paints the first page proves only that the query started. The complete-result time is what the user experiences when they export or scroll to the end.

Record both numbers with the query text, parameters and connection settings. Without that context the comparison is between two different jobs, not two locations.

Read the Wait Before the Network

SQL Server writes result rows into output buffers for the client to fetch, and a client that consumes slowly can make the server wait on that send. The wait type is ASYNC_NETWORK_IO, and Microsoft's troubleshooting note lists large results and client-side processing among its causes. The wait tells you that the send path is blocked, not why.

A slow VPN can contribute, but so can a client that formats each row, writes to a file, or pauses between batches. The wait name is a pointer to the next measurement, not a verdict about the link.

SELECT wait_type, wait_time_ms
FROM sys.dm_os_wait_stats
WHERE wait_type = 'ASYNC_NETWORK_IO';

Read the counter while the bounded workload runs, not after an idle hour, because cumulative counters mix every session since the instance started. Compare the delta across the run rather than the lifetime total. A growing delta during the transfer narrows the question to consumption or delivery.

Put Both Clients on the Same Clock

Run a bounded workload from a client close to the database and from the remote client. Keep query, parameters, result size and connection settings identical. Use the same measurement on both sides, because server execution time, grid display time and export time are three different clocks. Comparing a server-side number with a client-side export timer produces a conclusion that cannot be tested.

When the path looks responsible, have the network owner watch loss, retransmissions and achieved throughput for that specific flow while the transfer runs. A generic speed test may use another route, endpoint or concurrency pattern. A small successful request says little about a sustained result transfer.

Cut Bytes Before Blaming the Path

Filtering, aggregation and selecting only the needed columns reduce both transfer volume and the work the client does with each row. Preserve the intended result, because a report may need detail that an on-screen summary does not.

For repeatable exports, an approved execution location near the database can write a defined output that is then delivered once. That changes the workflow and its access controls, and it is not permission to leave an unrestricted dump on a shared host.

Compression is not the default repair. Support and security depend on the actual protocol and deployment, and a compressed stream that the client decompresses slowly can make the experience worse. Measure the stage first, then choose a supported change for that stage.

អត្ថបទពាក់ព័ន្ធ