Database
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Database

Kế hoạch thực thi Tác động đến ASYNC_NETWORK_IO Chờ - Phần 1

Một vài tuần trước, một câu hỏi thú vị đã được đặt ra trên thẻ băm #SQLHelp trên Twitter về tác động của các kế hoạch thực thi đối với kiểu chờ ASYNC_NETWORK_IO và nó đã tạo ra một số ý kiến ​​khác nhau và rất nhiều thảo luận hữu ích.

https://twitter.com/shawndube/status/1225476846537650176

Câu trả lời ngay lập tức của tôi cho vấn đề này là ai đó đang hiểu sai nguyên nhân và kết quả của việc này, vì kiểu chờ ASYNC_NETWORK_IO gặp phải khi Engine có kết quả để gửi TDS tới máy khách nhưng không có bộ đệm TDS khả dụng trên kết nối để gửi chúng trên. Nói chung, điều này có nghĩa là phía khách hàng không sử dụng kết quả một cách hiệu quả, nhưng dựa trên cuộc thảo luận sau đó, tôi đã đủ hấp dẫn để thực hiện một số thử nghiệm xem liệu một kế hoạch thực thi có thực sự tác động đáng kể đến việc chờ đợi ASYNC_NETWORK_IO hay không.

Tóm lại:Tập trung vào ASYNC_NETWORK_IO đợi một mình làm thước đo điều chỉnh là một sai lầm. Truy vấn thực thi càng nhanh thì kiểu chờ này càng có khả năng tích lũy cao hơn, ngay cả khi khách hàng đang sử dụng kết quả nhanh nhất có thể. (Cũng xem bài đăng gần đây của Greg về việc tập trung vào việc chờ đợi một mình nói chung.)

Cấu hình thử nghiệm

Để chạy các bài kiểm tra cho điều này, một bảng rất đơn giản đã được tạo dựa trên một ví dụ đã được cung cấp cho tôi qua email từ một thành viên khác của cộng đồng, cho thấy sự thay đổi trong kiểu chờ, nhưng cũng có một truy vấn hoàn toàn khác giữa hai các bài kiểm tra với một bảng bổ sung đang được sử dụng trong bài kiểm tra thứ hai và nó có một nhận xét để tắt kết quả, điều này sẽ loại bỏ phần quan trọng của loại chờ đợi này để bắt đầu, vì vậy nó không chỉ là một sự thay đổi kế hoạch đơn thuần.

Lưu ý:Tôi muốn chỉ ra rằng đây không phải là một tuyên bố tiêu cực đối với bất kỳ ai; cuộc thảo luận sau đó và các bài kiểm tra khác đến từ bản sao gốc đã được cung cấp rất mang tính giáo dục và nó dẫn đến việc nghiên cứu sâu hơn để hiểu tổng thể kiểu chờ đợi này. Bản sao gốc DID thể hiện sự khác biệt, nhưng với những thay đổi bổ sung không nằm trong câu hỏi ban đầu như đã đặt ra.

DROP TABLE IF EXISTS [DemoTable];
 
CREATE TABLE [DemoTable] (
  ID INT PRIMARY KEY,
  FILLER VARCHAR(100)
);
 
INSERT INTO [DemoTable] WITH (TABLOCK)
SELECT TOP (250000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)), REPLICATE('Z', 50)
  FROM master..spt_values t1
  CROSS JOIN master..spt_values t2
  CROSS JOIN master..spt_values t3
  OPTION (MAXDOP 1);
GO

Sử dụng bảng này làm tập dữ liệu cơ sở để thử nghiệm các hình dạng kế hoạch khác nhau bằng cách sử dụng gợi ý, các truy vấn sau đã được sử dụng:

SELECT t1.ID, t2.FILLER, t2.FILLER
  FROM [DemoTable] t1
  INNER HASH JOIN [DemoTable] t2 ON t1.ID = t2.ID;
 
  SELECT t1.ID, t2.FILLER, t2.FILLER
  FROM [DemoTable] t1
  INNER MERGE JOIN [DemoTable] t2 ON t1.ID = t2.ID;
 
  SELECT t1.ID, t2.FILLER, t2.FILLER
  FROM [DemoTable] t1
  INNER LOOP JOIN [DemoTable] t2 ON t1.ID = t2.ID;

Vì tôi đang chạy các truy vấn này trên SQL Server 2019 CU1, các kế hoạch thực thi bao gồm thông tin thống kê chờ thực tế liên quan đến việc thực thi truy vấn.

Lưu ý: Trình tối ưu hóa sẽ sử dụng Kết hợp Hợp nhất mà không áp dụng gợi ý cho tập dữ liệu và truy vấn cụ thể này.

Kết quả kiểm tra ban đầu

Đối với các thử nghiệm ban đầu, tôi chỉ sử dụng SSMS để chạy các truy vấn và thu thập kế hoạch Thực thi Thực tế để so sánh thông tin chờ được liên kết với từng truy vấn được hiển thị bên dưới. Lưu ý rằng đối với kích thước dữ liệu này, thời gian đã trôi qua không khác biệt đáng kể và thời gian chờ cũng không phải là số lượng chờ cho ASYNC_NETWORK_IO.

HASH THAM GIA

<WaitStats>
  <Wait WaitType="CXPACKET"         WaitTimeMs="18393" WaitCount="8415" />
  <Wait WaitType="ASYNC_NETWORK_IO" WaitTimeMs="4394"  WaitCount="6635" />
  <Wait WaitType="HTDELETE"         WaitTimeMs="957"   WaitCount="6"    />
  <Wait WaitType="HTBUILD"          WaitTimeMs="4"     WaitCount="6"    />
  <Wait WaitType="HTREPARTITION"    WaitTimeMs="3"     WaitCount="6"    />
  <Wait WaitType="CMEMTHREAD"       WaitTimeMs="3"     WaitCount="14"   />
  <Wait WaitType="LATCH_EX"         WaitTimeMs="2"     WaitCount="8"    />
</WaitStats>
<QueryTimeStats CpuTime="1068" ElapsedTime="4961" />

THAM GIA MERGE

<WaitStats>
  <Wait WaitType="ASYNC_NETWORK_IO" WaitTimeMs="3169" WaitCount="6592" />
</WaitStats>
<QueryTimeStats CpuTime="792" ElapsedTime="3933" />

ĐĂNG NHẬP THAM GIA

<WaitStats>
  <Wait WaitType="CXPACKET"         WaitTimeMs="13690" WaitCount="8286" />
  <Wait WaitType="ASYNC_NETWORK_IO" WaitTimeMs="3576"  WaitCount="6631" />
  <Wait WaitType="LATCH_EX"         WaitTimeMs="1"     WaitCount="3"    />
</WaitStats>
<QueryTimeStats CpuTime="2172" ElapsedTime="4084" />

Tuy nhiên, đây không phải là nơi tôi muốn dừng thử nghiệm, bởi vì kinh nghiệm của bản thân tôi đã nhiều lần cho thấy rằng Management Studio là người sử dụng kết quả từ SQL Server rất kém hiệu quả và chính nó có thể gây ra ASYNC_NETWORK_IO đang đợi xảy ra. Vì vậy, tôi quyết định thay đổi cách kiểm tra mọi thứ và chuyển sang thực thi SQLCMD của các truy vấn.

Kiểm tra với SQLCMD

Vì tôi sử dụng SQLCMD rất nhiều cho các bản demo trong khi trình bày, tôi đã tạo một tệp testscript.sql với nội dung sau:

PRINT 'Minimize Screen';
GO
 
WAITFOR DELAY '00:00:05';
GO
 
SELECT t1.ID, t2.FILLER, t2.FILLER
  FROM [DemoTable] t1
  INNER HASH JOIN [DemoTable] t2 ON t1.ID = t2.ID;
GO
 
SELECT t1.ID, t2.FILLER, t2.FILLER
  FROM [DemoTable] t1
  INNER MERGE JOIN [DemoTable] t2 ON t1.ID = t2.ID;
GO
 
SELECT t1.ID, t2.FILLER, t2.FILLER
  FROM [DemoTable] t1
  INNER LOOP JOIN [DemoTable] t2 ON t1.ID = t2.ID;
GO

Điều này được thực thi từ dòng lệnh như sau và trong khoảng thời gian trễ 5 giây, cửa sổ được thu nhỏ để cho phép việc thực thi không hiển thị và cuộn kết quả trong quá trình xử lý:

sqlcmd -S. \ SQL2019 -i testscript.sql -dAdventureWorks2017

Để nắm bắt các kế hoạch thực thi thực tế, tôi đã sử dụng phiên Sự kiện mở rộng thu thập sự kiện query_post_execution_showplan, theo nhận thức sâu sắc, trên SQL Server 2019, tôi nghĩ rằng tôi nên sử dụng query_post_execution_plan_profile thay thế để sử dụng thống kê thực thi truy vấn nhẹ cấu hình triển khai cơ sở hạ tầng v3, nhưng sự kiện này không trả về thông tin WaitStats hoặc QueryTimeStats trừ khi query_post_execution_showplan cũng được bật cùng lúc. Ngoài ra, vì đây là một máy kiểm tra biệt lập không có khối lượng công việc nào khác, nên các tác động của việc lập hồ sơ tiêu chuẩn không thực sự quá đáng lo ngại ở đây.

CREATE EVENT SESSION [Actual Plan] ON SERVER 
  ADD EVENT sqlserver.query_post_execution_showplan
  (ACTION(sqlserver.session_id));

HASH THAM GIA

<WaitStats>
  <Wait WaitType="CXPACKET"         WaitTimeMs="45722" WaitCount="8674" />
  <Wait WaitType="ASYNC_NETWORK_IO" WaitTimeMs="11321" WaitCount="6610" />
  <Wait WaitType="HTDELETE"         WaitTimeMs="1174"  WaitCount="6"    />
  <Wait WaitType="HTREPARTITION"    WaitTimeMs="4"     WaitCount="6"    />
  <Wait WaitType="HTBUILD"          WaitTimeMs="3"     WaitCount="5"    />
  <Wait WaitType="LATCH_EX"         WaitTimeMs="2"     WaitCount="7"    />
</WaitStats>
<QueryTimeStats ElapsedTime="11874" CpuTime="1070" />

THAM GIA MERGE

<WaitStats>
  <Wait WaitType="ASYNC_NETWORK_IO" WaitTimeMs="10837" WaitCount="6602" />
</WaitStats>
<QueryTimeStats ElapsedTime="11597" CpuTime="789" />

ĐĂNG NHẬP THAM GIA

<WaitStats>
  <Wait WaitType="CXPACKET"         WaitTimeMs="43587" WaitCount="8620" />
  <Wait WaitType="ASYNC_NETWORK_IO" WaitTimeMs="11177" WaitCount="6612" />
  <Wait WaitType="LATCH_EX"         WaitTimeMs="1"     WaitCount="3"    />
</WaitStats>
<QueryTimeStats ElapsedTime="11696" CpuTime="2221" />

Đây thực sự không phải là cách nhanh hơn để thực hiện truy vấn và hiệu suất thực sự đã bị giảm khi sử dụng tiện ích dòng lệnh để thực hiện truy vấn, ngay cả khi cửa sổ được thu nhỏ và không hiển thị kết quả cuộn. Với cửa sổ đang mở, thời gian thực thi HASH là 15708ms và thời gian chờ ASYNC_NETWORK_IO là 15126ms. Tuy nhiên, điều này chứng tỏ rằng cho cùng một kết quả chính xác, hiệu suất của máy khách sử dụng kết quả sẽ ảnh hưởng đến cả thời gian chờ và thời gian thực hiện truy vấn.

Tác động song song?

Một trong những điều tôi nhận thấy là chỉ có hai trong số các kế hoạch được thực thi song song, dựa trên sự tồn tại của CXPACKET và LATCH_EX chờ trong XML kế hoạch thực thi. Vì vậy, tôi tự hỏi loại tác động nào buộc một kế hoạch thực thi nối tiếp sẽ có đối với việc thực hiện các truy vấn tương tự này bằng cách sử dụng TÙY CHỌN (MAXDOP 1).

HASH THAM GIA

<WaitStats>
  <Wait WaitType="ASYNC_NETWORK_IO" WaitTimeMs="4047" WaitCount="6379" />
</WaitStats>
<QueryTimeStats CpuTime="602" ElapsedTime="4619" />

THAM GIA MERGE

<WaitStats>
  <Wait WaitType="ASYNC_NETWORK_IO" WaitTimeMs="3699" WaitCount="6608" />
</WaitStats>
<QueryTimeStats CpuTime="810" ElapsedTime="4478" />

ĐĂNG NHẬP THAM GIA

<WaitStats>
  <Wait WaitType="ASYNC_NETWORK_IO" WaitTimeMs="2083" WaitCount="5385" />
</WaitStats>
<QueryTimeStats CpuTime="1859" ElapsedTime="3918" />

Lưu ý ở đây rằng tổng số lần chờ đợi không giảm đáng kể. Chỉ có kế hoạch tham gia vòng lặp nối tiếp có sự thay đổi lớn về số lần chờ hoặc tổng thời gian chờ được liên kết với nó và riêng điều này không có nghĩa là đó là một lợi ích tích cực, thời gian thực thi cho truy vấn không được cải thiện đáng kể và có thể có các yếu tố khác ảnh hưởng đến kết quả của thử nghiệm cụ thể đó.

Bảng dưới đây tóm tắt thời gian chờ ASYNC_NETWORK_IO và tính cho từng bài kiểm tra.

PlanType Hàng WaitCount Thời gian chờ Thời gian thực thi Tên ứng dụng MAXDOP 1 Song song
Băm 250.000 6,635 4.394 4,961 SSMS N Y
Hợp nhất 250.000 6,592 3.169 3,933 SSMS N N
Vòng lặp 250.000 6,631 3.576 4.084 SSMS N Y
Băm 250.000 6,610 11.321 11.874 SQLCMD N Y
Hợp nhất 250.000 6,602 10.837 11,597 SQLCMD N N
Vòng lặp 250.000 6,612 11,177 11.696 SQLCMD N Y
Băm 250.000 6.379 4.047 4.619 SSMS Y N
Hợp nhất 250.000 6,608 3.699 4,479 SSMS Y N
Vòng lặp 250.000 5.385 2.083 3,918 SSMS Y N

Tóm tắt

Mặc dù cuộc điều tra của bài đăng này không bao gồm mọi khía cạnh của thay đổi kế hoạch hoặc kiểu chờ ASYNC_NETWORK_IO, nhưng nó chứng minh rằng việc chờ đợi này không bị ảnh hưởng đáng kể bởi kế hoạch thực thi được sử dụng để thực hiện truy vấn. Tôi sẽ phân loại kiểu chờ này gần giống như kiểu đợi CXPACKET khi thực hiện phân tích tổng thể một máy chủ; bình thường để xem đối với hầu hết các khối lượng công việc và trừ khi nó cực kỳ sai lệch và có các vấn đề hiệu suất khác dẫn đến việc máy khách tiêu thụ chậm kết quả như chặn bằng trình chặn khách hàng tiềm năng đang chờ ASYNC_NETWORK_IO, thì điều gì đó sẽ được bỏ qua vì chỉ là 'một phần của chữ ký chờ đợi thông thường khối lượng công việc '.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Theo dõi các tùy chọn con trỏ

  2. Tìm hiểu về sự tuôn ra của bộ đệm nhật ký

  3. Các nguyên tắc cơ bản về biểu thức bảng, Phần 1

  4. Di chuyển DB với Trình hướng dẫn Đa bảng NextForm

  5. Làm thế nào để thêm khóa ngoại trong SQL?