Why does a simple loop result in ASYNC_NETWORK_IO waits?Slow temp table drops in sql 2005Why is there ASYNC_NETWORK_IO wait type on Shared Memory connections?SPIDs stuck indefinitely in suspended stateGet specific result without using loopWhy do async_network_io wait types occur?Large Variation in Bulk Insert timeDoes dm_exec_procedure_stats.total_worker_time include signal waits?Why does a plan with FULL optimization show simple parameterization?Increased waits during checkpoint after upgrading to better storageSimple recursive CTE stuck in infinite loop

Hero deduces identity of a killer

Why does AES have exactly 10 rounds for a 128-bit key, 12 for 192 bits and 14 for a 256-bit key size?

Picking the different solutions to the time independent Schrodinger eqaution

How should I respond when I lied about my education and the company finds out through background check?

Why does a simple loop result in ASYNC_NETWORK_IO waits?

Angel of Condemnation - Exile creature with second ability

Fear of getting stuck on one programming language / technology that is not used in my country

Can the US President recognize Israel’s sovereignty over the Golan Heights for the USA or does that need an act of Congress?

What should you do if you miss a job interview (deliberately)?

Multiplicative persistence

15% tax on $7.5k earnings. Is that right?

Why is so much work done on numerical verification of the Riemann Hypothesis?

How to explain what's wrong with this application of the chain rule?

Limits and Infinite Integration by Parts

Does an advisor owe his/her student anything? Will an advisor keep a PhD student only out of pity?

How to cover method return statement in Apex Class?

Mimic lecturing on blackboard, facing audience

Quoting Keynes in a lecture

Why should universal income be universal?

Terse Method to Swap Lowest for Highest?

Why would a new[] expression ever invoke a destructor?

Is aluminum electrical wire used on aircraft?

On a tidally locked planet, would time be quantized?

PTIJ: Haman's bad computer



Why does a simple loop result in ASYNC_NETWORK_IO waits?


Slow temp table drops in sql 2005Why is there ASYNC_NETWORK_IO wait type on Shared Memory connections?SPIDs stuck indefinitely in suspended stateGet specific result without using loopWhy do async_network_io wait types occur?Large Variation in Bulk Insert timeDoes dm_exec_procedure_stats.total_worker_time include signal waits?Why does a plan with FULL optimization show simple parameterization?Increased waits during checkpoint after upgrading to better storageSimple recursive CTE stuck in infinite loop













14















The following T-SQL takes about 25 seconds on my machine with SSMS v17.9:



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;


It accumulates 532 ms of ASYNC_NETWORK_IO waits according to both sys.dm_exec_session_wait_stats and sys.dm_os_wait_stats. The total wait time increases as the number of loop iterations increases. Using the wait_completed extended event I can see that the wait happens roughly every 43 ms with a few exceptions:



wait table



In addition, I can get the call stacks that occur right before the ASYNC_NETWORK_IO wait:



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


Finally, I noticed that SSMS uses a surprising amount of CPU during the loop (about half a core on average). I'm unable to figure out what SSMS is doing during that time.



Why does a simple loop cause ASYNC_NETWORK_IOwaits when executed through SSMS? The only output that I appear to get from the client from this query execution is the "Commands completed successfully." message.










share|improve this question






















  • SSMS blows its CPU on appending rows to the results grid. Enable “discard results after query execution” and SSMS will read the row then drop it. Your waits should go down.

    – ta.speot.is
    3 hours ago















14















The following T-SQL takes about 25 seconds on my machine with SSMS v17.9:



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;


It accumulates 532 ms of ASYNC_NETWORK_IO waits according to both sys.dm_exec_session_wait_stats and sys.dm_os_wait_stats. The total wait time increases as the number of loop iterations increases. Using the wait_completed extended event I can see that the wait happens roughly every 43 ms with a few exceptions:



wait table



In addition, I can get the call stacks that occur right before the ASYNC_NETWORK_IO wait:



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


Finally, I noticed that SSMS uses a surprising amount of CPU during the loop (about half a core on average). I'm unable to figure out what SSMS is doing during that time.



Why does a simple loop cause ASYNC_NETWORK_IOwaits when executed through SSMS? The only output that I appear to get from the client from this query execution is the "Commands completed successfully." message.










share|improve this question






















  • SSMS blows its CPU on appending rows to the results grid. Enable “discard results after query execution” and SSMS will read the row then drop it. Your waits should go down.

    – ta.speot.is
    3 hours ago













14












14








14


1






The following T-SQL takes about 25 seconds on my machine with SSMS v17.9:



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;


It accumulates 532 ms of ASYNC_NETWORK_IO waits according to both sys.dm_exec_session_wait_stats and sys.dm_os_wait_stats. The total wait time increases as the number of loop iterations increases. Using the wait_completed extended event I can see that the wait happens roughly every 43 ms with a few exceptions:



wait table



In addition, I can get the call stacks that occur right before the ASYNC_NETWORK_IO wait:



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


Finally, I noticed that SSMS uses a surprising amount of CPU during the loop (about half a core on average). I'm unable to figure out what SSMS is doing during that time.



Why does a simple loop cause ASYNC_NETWORK_IOwaits when executed through SSMS? The only output that I appear to get from the client from this query execution is the "Commands completed successfully." message.










share|improve this question














The following T-SQL takes about 25 seconds on my machine with SSMS v17.9:



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;


It accumulates 532 ms of ASYNC_NETWORK_IO waits according to both sys.dm_exec_session_wait_stats and sys.dm_os_wait_stats. The total wait time increases as the number of loop iterations increases. Using the wait_completed extended event I can see that the wait happens roughly every 43 ms with a few exceptions:



wait table



In addition, I can get the call stacks that occur right before the ASYNC_NETWORK_IO wait:



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


Finally, I noticed that SSMS uses a surprising amount of CPU during the loop (about half a core on average). I'm unable to figure out what SSMS is doing during that time.



Why does a simple loop cause ASYNC_NETWORK_IOwaits when executed through SSMS? The only output that I appear to get from the client from this query execution is the "Commands completed successfully." message.







sql-server ssms






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked yesterday









Joe ObbishJoe Obbish

21.4k43188




21.4k43188












  • SSMS blows its CPU on appending rows to the results grid. Enable “discard results after query execution” and SSMS will read the row then drop it. Your waits should go down.

    – ta.speot.is
    3 hours ago

















  • SSMS blows its CPU on appending rows to the results grid. Enable “discard results after query execution” and SSMS will read the row then drop it. Your waits should go down.

    – ta.speot.is
    3 hours ago
















SSMS blows its CPU on appending rows to the results grid. Enable “discard results after query execution” and SSMS will read the row then drop it. Your waits should go down.

– ta.speot.is
3 hours ago





SSMS blows its CPU on appending rows to the results grid. Enable “discard results after query execution” and SSMS will read the row then drop it. Your waits should go down.

– ta.speot.is
3 hours ago










1 Answer
1






active

oldest

votes


















21














The documentation for SET NOCOUNT says:




SET NOCOUNT ON prevents the sending of DONE_IN_PROC messages to the client for each statement in a stored procedure. For stored procedures that contain several statements that do not return much actual data, or for procedures that contain Transact-SQL loops, setting SET NOCOUNT to ON can provide a significant performance boost, because network traffic is greatly reduced.




You are not running the statements in a stored procedure, so SQL Server sends DONE tokens (code 0xFD) to indicate the completion status of each SQL statement. These messages are deferred, and sent asynchronously when the network packet is full. When the client does not consume network packets quickly enough, eventually the buffers fill up, and the operation becomes blocking for SQL Server, generating the ASYNC_NETWORK_IO waits.



Note the DONE tokens are different from DONEINPROC (code 0xFF) as the documentation notes:




  • A DONE token is returned for each SQL statement in the SQL batch except variable declarations.


  • For execution of SQL statements within stored procedures, DONEPROC and DONEINPROC tokens are used in place of DONE tokens.




You will see a dramatic reduction in ASYNC_NETWORK_IO waits using:



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;


You could also use sys.sp_executesql to achieve the same result.



Example stack trace captured just as an ASYNC_NETWORK_IO wait begins:



sending a packet



An example TDS packet as seen in the inline function sqllang!srv_completioncode_ex<1> had the following 13 bytes:



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


Which decodes to:



  • TokenType = 0xfd DONE_TOKEN

  • Status = 0x0001 DONE_MORE

  • CurCmd = 0x00c1 (193)

  • DoneRowCount = 0x00000001 (1)

Ultimately, the number of ASYNC_NETWORK_IO waits depends on the client and driver, and what it does, if anything, with all the DONE messages. Testing with a loop 1/10th of the size given in the question (5,000,000 loop iterations) I found SSMS ran for about 4 seconds with 200-300 ms of waits. sqlcmd ran for 2-3 seconds with single digit ms waits; osql around the same run time with around 10 ms of waits.



The worst client by far for this test was Azure Data Studio. It ran for almost 6 hours:



ADS






share|improve this answer
























    Your Answer








    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "182"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f232816%2fwhy-does-a-simple-loop-result-in-async-network-io-waits%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    21














    The documentation for SET NOCOUNT says:




    SET NOCOUNT ON prevents the sending of DONE_IN_PROC messages to the client for each statement in a stored procedure. For stored procedures that contain several statements that do not return much actual data, or for procedures that contain Transact-SQL loops, setting SET NOCOUNT to ON can provide a significant performance boost, because network traffic is greatly reduced.




    You are not running the statements in a stored procedure, so SQL Server sends DONE tokens (code 0xFD) to indicate the completion status of each SQL statement. These messages are deferred, and sent asynchronously when the network packet is full. When the client does not consume network packets quickly enough, eventually the buffers fill up, and the operation becomes blocking for SQL Server, generating the ASYNC_NETWORK_IO waits.



    Note the DONE tokens are different from DONEINPROC (code 0xFF) as the documentation notes:




    • A DONE token is returned for each SQL statement in the SQL batch except variable declarations.


    • For execution of SQL statements within stored procedures, DONEPROC and DONEINPROC tokens are used in place of DONE tokens.




    You will see a dramatic reduction in ASYNC_NETWORK_IO waits using:



    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;


    You could also use sys.sp_executesql to achieve the same result.



    Example stack trace captured just as an ASYNC_NETWORK_IO wait begins:



    sending a packet



    An example TDS packet as seen in the inline function sqllang!srv_completioncode_ex<1> had the following 13 bytes:



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


    Which decodes to:



    • TokenType = 0xfd DONE_TOKEN

    • Status = 0x0001 DONE_MORE

    • CurCmd = 0x00c1 (193)

    • DoneRowCount = 0x00000001 (1)

    Ultimately, the number of ASYNC_NETWORK_IO waits depends on the client and driver, and what it does, if anything, with all the DONE messages. Testing with a loop 1/10th of the size given in the question (5,000,000 loop iterations) I found SSMS ran for about 4 seconds with 200-300 ms of waits. sqlcmd ran for 2-3 seconds with single digit ms waits; osql around the same run time with around 10 ms of waits.



    The worst client by far for this test was Azure Data Studio. It ran for almost 6 hours:



    ADS






    share|improve this answer





























      21














      The documentation for SET NOCOUNT says:




      SET NOCOUNT ON prevents the sending of DONE_IN_PROC messages to the client for each statement in a stored procedure. For stored procedures that contain several statements that do not return much actual data, or for procedures that contain Transact-SQL loops, setting SET NOCOUNT to ON can provide a significant performance boost, because network traffic is greatly reduced.




      You are not running the statements in a stored procedure, so SQL Server sends DONE tokens (code 0xFD) to indicate the completion status of each SQL statement. These messages are deferred, and sent asynchronously when the network packet is full. When the client does not consume network packets quickly enough, eventually the buffers fill up, and the operation becomes blocking for SQL Server, generating the ASYNC_NETWORK_IO waits.



      Note the DONE tokens are different from DONEINPROC (code 0xFF) as the documentation notes:




      • A DONE token is returned for each SQL statement in the SQL batch except variable declarations.


      • For execution of SQL statements within stored procedures, DONEPROC and DONEINPROC tokens are used in place of DONE tokens.




      You will see a dramatic reduction in ASYNC_NETWORK_IO waits using:



      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;


      You could also use sys.sp_executesql to achieve the same result.



      Example stack trace captured just as an ASYNC_NETWORK_IO wait begins:



      sending a packet



      An example TDS packet as seen in the inline function sqllang!srv_completioncode_ex<1> had the following 13 bytes:



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


      Which decodes to:



      • TokenType = 0xfd DONE_TOKEN

      • Status = 0x0001 DONE_MORE

      • CurCmd = 0x00c1 (193)

      • DoneRowCount = 0x00000001 (1)

      Ultimately, the number of ASYNC_NETWORK_IO waits depends on the client and driver, and what it does, if anything, with all the DONE messages. Testing with a loop 1/10th of the size given in the question (5,000,000 loop iterations) I found SSMS ran for about 4 seconds with 200-300 ms of waits. sqlcmd ran for 2-3 seconds with single digit ms waits; osql around the same run time with around 10 ms of waits.



      The worst client by far for this test was Azure Data Studio. It ran for almost 6 hours:



      ADS






      share|improve this answer



























        21












        21








        21







        The documentation for SET NOCOUNT says:




        SET NOCOUNT ON prevents the sending of DONE_IN_PROC messages to the client for each statement in a stored procedure. For stored procedures that contain several statements that do not return much actual data, or for procedures that contain Transact-SQL loops, setting SET NOCOUNT to ON can provide a significant performance boost, because network traffic is greatly reduced.




        You are not running the statements in a stored procedure, so SQL Server sends DONE tokens (code 0xFD) to indicate the completion status of each SQL statement. These messages are deferred, and sent asynchronously when the network packet is full. When the client does not consume network packets quickly enough, eventually the buffers fill up, and the operation becomes blocking for SQL Server, generating the ASYNC_NETWORK_IO waits.



        Note the DONE tokens are different from DONEINPROC (code 0xFF) as the documentation notes:




        • A DONE token is returned for each SQL statement in the SQL batch except variable declarations.


        • For execution of SQL statements within stored procedures, DONEPROC and DONEINPROC tokens are used in place of DONE tokens.




        You will see a dramatic reduction in ASYNC_NETWORK_IO waits using:



        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;


        You could also use sys.sp_executesql to achieve the same result.



        Example stack trace captured just as an ASYNC_NETWORK_IO wait begins:



        sending a packet



        An example TDS packet as seen in the inline function sqllang!srv_completioncode_ex<1> had the following 13 bytes:



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


        Which decodes to:



        • TokenType = 0xfd DONE_TOKEN

        • Status = 0x0001 DONE_MORE

        • CurCmd = 0x00c1 (193)

        • DoneRowCount = 0x00000001 (1)

        Ultimately, the number of ASYNC_NETWORK_IO waits depends on the client and driver, and what it does, if anything, with all the DONE messages. Testing with a loop 1/10th of the size given in the question (5,000,000 loop iterations) I found SSMS ran for about 4 seconds with 200-300 ms of waits. sqlcmd ran for 2-3 seconds with single digit ms waits; osql around the same run time with around 10 ms of waits.



        The worst client by far for this test was Azure Data Studio. It ran for almost 6 hours:



        ADS






        share|improve this answer















        The documentation for SET NOCOUNT says:




        SET NOCOUNT ON prevents the sending of DONE_IN_PROC messages to the client for each statement in a stored procedure. For stored procedures that contain several statements that do not return much actual data, or for procedures that contain Transact-SQL loops, setting SET NOCOUNT to ON can provide a significant performance boost, because network traffic is greatly reduced.




        You are not running the statements in a stored procedure, so SQL Server sends DONE tokens (code 0xFD) to indicate the completion status of each SQL statement. These messages are deferred, and sent asynchronously when the network packet is full. When the client does not consume network packets quickly enough, eventually the buffers fill up, and the operation becomes blocking for SQL Server, generating the ASYNC_NETWORK_IO waits.



        Note the DONE tokens are different from DONEINPROC (code 0xFF) as the documentation notes:




        • A DONE token is returned for each SQL statement in the SQL batch except variable declarations.


        • For execution of SQL statements within stored procedures, DONEPROC and DONEINPROC tokens are used in place of DONE tokens.




        You will see a dramatic reduction in ASYNC_NETWORK_IO waits using:



        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;


        You could also use sys.sp_executesql to achieve the same result.



        Example stack trace captured just as an ASYNC_NETWORK_IO wait begins:



        sending a packet



        An example TDS packet as seen in the inline function sqllang!srv_completioncode_ex<1> had the following 13 bytes:



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


        Which decodes to:



        • TokenType = 0xfd DONE_TOKEN

        • Status = 0x0001 DONE_MORE

        • CurCmd = 0x00c1 (193)

        • DoneRowCount = 0x00000001 (1)

        Ultimately, the number of ASYNC_NETWORK_IO waits depends on the client and driver, and what it does, if anything, with all the DONE messages. Testing with a loop 1/10th of the size given in the question (5,000,000 loop iterations) I found SSMS ran for about 4 seconds with 200-300 ms of waits. sqlcmd ran for 2-3 seconds with single digit ms waits; osql around the same run time with around 10 ms of waits.



        The worst client by far for this test was Azure Data Studio. It ran for almost 6 hours:



        ADS







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited 7 hours ago

























        answered 23 hours ago









        Paul WhitePaul White

        53.5k14285458




        53.5k14285458



























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Database Administrators Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f232816%2fwhy-does-a-simple-loop-result-in-async-network-io-waits%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Luettelo Yhdysvaltain laivaston lentotukialuksista Lähteet | Navigointivalikko

            Adding axes to figuresAdding axes labels to LaTeX figuresLaTeX equivalent of ConTeXt buffersRotate a node but not its content: the case of the ellipse decorationHow to define the default vertical distance between nodes?TikZ scaling graphic and adjust node position and keep font sizeNumerical conditional within tikz keys?adding axes to shapesAlign axes across subfiguresAdding figures with a certain orderLine up nested tikz enviroments or how to get rid of themAdding axes labels to LaTeX figures

            Gary (muusikko) Sisällysluettelo Historia | Rockin' High | Lähteet | Aiheesta muualla | NavigointivalikkoInfobox OKTuomas "Gary" Keskinen Ancaran kitaristiksiProjekti Rockin' High