VPN 上的大型 SQL 结果:数据行在哪里等待
大型 SQL 结果会在三个地方等待:服务器缓冲区、VPN 路径和客户端。在更改带宽或启用压缩之前,先测量每个阶段。
查询可能在毫秒内完成,却仍要花几分钟才能通过 VPN 到达笔记本。服务器把行写入缓冲区,连接负责传输,客户端负责消费,而这些阶段是重叠的,而不是依次进行。其中任何一个都可能成为瓶颈。在更改带宽或启用压缩之前,先找出真正在等待的阶段。
三个阶段,一只秒表
把计时器拆成两个含义不同的数字:第一行可用的时刻,以及最后一行被消费的时刻。画出第一页的表格只能证明查询已经开始。完整结果的时间,才是用户导出或滚动到末尾时实际体验到的。
把这两个数字与查询文本、参数和连接设置一起记录下来。没有这些上下文,比较的是两个不同的任务,而不是两个位置。
先看等待,再看网络
SQL Server 把结果行写入输出缓冲区供客户端读取,消费缓慢的客户端会让服务器在该发送上等待。等待类型是 ASYNC_NETWORK_IO,Microsoft 的故障排除说明把大型结果和客户端侧处理列为原因之一。这个等待说明发送路径被阻塞,但并没有说明原因。
慢速 VPN 可能是原因之一,但逐行格式化、写入文件或在批次之间暂停的客户端同样可能是原因。等待名称只是指向下一次测量的线索,而不是对链路的判决。
SELECT wait_type, wait_time_ms
FROM sys.dm_os_wait_stats
WHERE wait_type = 'ASYNC_NETWORK_IO';
要在有限负载运行的期间读取计数器,而不是在空闲一小时之后,因为累计计数器混入了实例启动以来的所有会话。比较本次运行的增量,而不是整个生命周期的总量。传输期间增量持续增长,就把问题缩小到消费或交付环节。
让两个客户端使用同一只时钟
从靠近数据库的客户端和远程客户端分别运行同样的有限负载。保持查询、参数、结果大小和连接设置完全一致。两侧使用同一种测量方式,因为服务器执行时间、表格显示时间和导出时间是三只不同的时钟。把服务器端的数字与客户端的导出计时器相比,得到的结论无法验证。
如果怀疑路径有问题,让网络负责人在传输运行期间观察该特定流的丢包、重传和实际吞吐。通用的速度测试可能走另一条路由、另一个端点或另一种并发模式。一个小请求成功,并不能说明持续的结果传输没问题。
先削减字节,再指责路径
过滤、聚合以及只选择需要的列,既能减少传输量,也能减少客户端处理每一行的工作。要保留预期的结果,因为报表可能需要屏幕摘要里没有的细节。
对于可重复的导出,靠近数据库的获批执行位置可以写出定义好的输出,然后只交付一次。这会改变工作流及其访问控制,并不等于允许在共享主机上留下不受限制的导出文件。
压缩不是默认的修复手段。支持与安全取决于实际协议和部署方式,而客户端解压缓慢的压缩流反而可能让体验更差。先测量阶段,再为该阶段选择受支持的改动。