AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 232816
Accepted
Joe Obbish
Joe Obbish
Asked: 2019-03-22 20:21:55 +0800 CST2019-03-22 20:21:55 +0800 CST 2019-03-22 20:21:55 +0800 CST

为什么一个简单的循环会导致 ASYNC_NETWORK_IO 等待?

  • 772

以下 T-SQL 在我的机器上使用 SSMS v17.9 大约需要 25 秒:

DECLARE @outer_loop INT = 0,
@big_string_for_u VARCHAR(8000);

SET NOCOUNT ON;

WHILE @outer_loop < 50000000
BEGIN
    SET @big_string_for_u = 'ZZZZZZZZZZ';
    SET @outer_loop = @outer_loop + 1;
END;

ASYNC_NETWORK_IO根据sys.dm_exec_session_wait_stats和,它累积了 532 毫秒的等待时间sys.dm_os_wait_stats。总等待时间随着循环迭代次数的增加而增加。使用wait_completed扩展事件,我可以看到等待大约每 43 毫秒发生一次,但有一些例外:

等候桌

此外,我可以获取在ASYNC_NETWORK_IO等待之前发生的调用堆栈:

sqldk.dll!SOS_DispatcherBase::GetTrack+0x7f6c
sqldk.dll!SOS_Scheduler::PromotePendingTask+0x204
sqldk.dll!SOS_Task::PostWait+0x5f
sqldk.dll!SOS_Scheduler::Suspend+0xb15
sqllang.dll!CSECCNGProvider::GetBCryptHandleFromAlgID+0xf6af
sqllang.dll!CSECCNGProvider::GetBCryptHandleFromAlgID+0xf44c
sqllang.dll!SNIPacketRelease+0xd63
sqllang.dll!SNIPacketRelease+0x2097
sqllang.dll!SNIPacketRelease+0x1f99
sqllang.dll!SNIPacketRelease+0x18fe
sqllang.dll!CAutoExecuteAsContext::Restore+0x52d
sqllang.dll!CSQLSource::Execute+0x151b
sqllang.dll!CSQLSource::Execute+0xe13
sqllang.dll!CSQLSource::Execute+0x474
sqllang.dll!SNIPacketRelease+0x165d
sqllang.dll!CValOdsRow::CValOdsRow+0xa92
sqllang.dll!CValOdsRow::CValOdsRow+0x883
sqldk.dll!ClockHand::Statistic::RecordClockHandStats+0x15d
sqldk.dll!ClockHand::Statistic::RecordClockHandStats+0x638
sqldk.dll!ClockHand::Statistic::RecordClockHandStats+0x2ad
sqldk.dll!SystemThread::MakeMiniSOSThread+0xdf8
sqldk.dll!SystemThread::MakeMiniSOSThread+0xf00
sqldk.dll!SystemThread::MakeMiniSOSThread+0x667
sqldk.dll!SystemThread::MakeMiniSOSThread+0xbb9

最后,我注意到 SSMS 在循环期间使用了惊人数量的 CPU(平均大约半个核心)。我无法弄清楚 SSMS 在那段时间里在做什么。

为什么一个简单的循环ASYNC_NETWORK_IO在通过 SSMS 执行时会导致等待?我似乎从该查询执行中从客户端获得的唯一输出是“命令已成功完成”。信息。

sql-server ssms
  • 1 1 个回答
  • 2410 Views

1 个回答

  • Voted
  1. Best Answer
    Paul White
    2019-03-22T22:42:40+08:002019-03-22T22:42:40+08:00

    的文档SET NOCOUNT说:

    SET NOCOUNT ON防止DONE_IN_PROC为存储过程中的每个语句向客户端发送消息。对于包含不返回太多实际数据的多个语句的存储过程,或者对于包含 Transact-SQL 循环的过程,设置SET NOCOUNT为ON可以显着提高性能,因为网络流量大大减少。

    您没有在存储过程中运行语句,因此 SQL Server 发送DONE令牌(代码0xFD)来指示每个 SQL 语句的完成状态。这些消息被延迟,并在网络数据包已满时异步发送。当客户端没有足够快地消耗网络数据包时,最终缓冲区会填满,并且操作会阻塞 SQL Server,从而产生ASYNC_NETWORK_IO等待。

    请注意,DONE令牌与文档说明的DONEINPROC(code ) 不同:0xFF

    • DONE为 SQL 批处理中的每个 SQL 语句返回一个标记,变量声明除外。

    • 为了在存储过程中执行 SQL 语句,DONEPROC使用DONEINPROC标记代替DONE标记。

    您将看到使用以下命令显着减少ASYNC_NETWORK_IO等待:

    CREATE PROCEDURE #P AS
    SET NOCOUNT ON;
    
    DECLARE
        @outer_loop integer = 0,
        @big_string_for_u varchar(8000);
    
    
    WHILE @outer_loop < 5000000
    BEGIN
        SET @big_string_for_u = 'ZZZZZZZZZZ';
        SET @outer_loop = @outer_loop + 1;
    END;
    GO
    EXECUTE dbo.#P;
    

    您也可以使用sys.sp_executesql来达到相同的结果。

    ASYNC_NETWORK_IO在等待开始时捕获的示例堆栈跟踪:

    发送数据包

    在内联函数中看到的示例 TDS 数据包sqllang!srv_completioncode_ex<1>具有以下 13 个字节:

    fd 01 00 c1 00 01 00 00 00 00 00 00 00          
    

    解码为:

    • 令牌类型 = 0xfdDONE_TOKEN
    • 状态 = 0x0001DONE_MORE
    • CurCmd = 0x00c1 (193)
    • DoneRowCount = 0x00000001 (1)

    最终,ASYNC_NETWORK_IO等待的次数取决于客户端和驱动程序,以及它对所有DONE消息的作用(如果有的话)。使用问题中给出的大小的 1/10 循环进行测试(5,000,000 次循环迭代)我发现 SSMS 运行了大约 4 秒,等待时间为 200-300 毫秒。sqlcmd以个位数毫秒等待运行 2-3 秒;osql大约相同的运行时间,大约 10 毫秒的等待。

    迄今为止,该测试最差的客户端是 Azure Data Studio。它运行了将近 6 个小时:

    广告

    • 37

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve