針對ASYNC_NETWORK_IO等候類型所產生的慢速查詢進行疑難解答
徵兆
當 SQL Server 產生結果集並將其傳送至用戶端應用程式時,會將結果放入輸出緩衝區中,用戶端應用程式會從輸出緩衝區擷取它們。 如果用戶端應用程式停止或未擷取結果,SQL Server 必須等到確認用戶端應用程式在傳送更多結果之前,已收到所有結果。 這個等候會顯示為 ASYNC_NETWORK_IO
。 如需詳細資訊,請參閱 瞭解 SQL Server 中的ASYNC_NETWORK_IO等候影片。
過度ASYNC_NETWORK_IO等候可能會導致兩個問題:
查詢可能會變慢,因為它們的總持續時間較長。
當 SQL Server 在等候用戶端擷取結果時,無法釋放獲得的鎖定。 如果鎖定已許久未釋放,SQL Server 上將會封鎖其他工作階段。
原因和解決方式
下列各節列出此等候類型的常見原因,以及解決此問題的對應步驟:
大型結果集
有些應用程式用戶端會要求數千或甚至數百萬個數據列,然後套用篩選、排序和匯總來處理結果。 大型結果集可能會導致不必要的網路使用率和用戶端應用程式處理。
解決方案: 應用程式開發人員必須仔細平衡 SQL Server 與客戶端之間的處理。 篩選或匯總可由 SQL Server 執行,而最終的結果集可能很小。 限制抵達客戶端的結果集。 在收到數據之後,用戶端上會更適當地計算數據、呈現和格式設定。
應用程式無法快速擷取結果
如果用戶端應用程式不夠快地擷取結果,而且不會通知 SQL Server 已收到結果集,則 ASYNC_NETWORK_IO
等候會在伺服器上發生。
為了說明如何使用 ADO.NET,DataSet 和 DataTable 預設會擷取所有數據列以完成,然後用戶端才能存取它。 不過,SqlDataReader 之類的類別可讓應用程式開發人員選擇從伺服器擷取每個數據列之後要執行的動作。 應用程式可以一次擷取一個數據列,然後根據商務需求處理此數據列。 例如:
將數據列寫入檔案。
透過網路將數據列傳送至另一個應用程式。
等候一段時間或用戶輸入。
解決方式: 若要解決此問題,請使用緊密的 WHILE/FOR 迴圈,盡可能快速地擷取用戶端的所有結果。 這表示儲存會導致記憶體中,然後才進行更多處理。
用戶端應用程式電腦處於壓力之下(I/O、記憶體或 CPU)
即使開發應用程式程式代碼以儘快擷取結果,系統資源問題可能會導致整個用戶端程式變慢。 例如:
如果執行用戶端應用程式的電腦具有資源限制,應用程式可能無法快速擷取結果。 例如:
100% CPU 使用率
記憶體不足(已取用所有記憶體)
I/O 變慢(可能是應用程式寫入結果或記錄檔)
這些資源條件約束可能會導致傳入結果的處理速度變慢,並導致 SQL Server 體驗等候類型 ASYNC_NETWORK_IO
。
解決方案:若要解決此問題,請使用 效能監視器 之類的工具來診斷執行應用程式的系統,然後排除任何資源條件約束。 下列其中一種方法可能適合您:
停止其他應用程式執行。
修正這些應用程式中的任何程式碼問題。
如果應用程式已完全調整,請升級系統上的硬體。
NIC/網路
網路或網路介面卡 (NIC) 變慢可能會導致網路流量延遲,而且自然會延遲擷取結果及與 SQL Server 的通訊。 網路延遲通常是以下問題所造成:
網路介面卡驅動程式問題
網路篩選驅動程式問題
設定錯誤或故障的防火牆
路由器問題
由於流量而造成多載的網路 (較不常見)
解決方案: 若要診斷這些問題,您可以 收集網路追蹤 ,並尋找封包重設和重新傳輸。 然後,您可以解決網路相關問題,以消除封包重設/重新傳輸。