Database
 sql >> Teknologi Basis Data >  >> RDS >> Database

Dampak Rencana Eksekusi pada ASYNC_NETWORK_IO Menunggu – Bagian 1

Beberapa minggu yang lalu, sebuah pertanyaan menarik diajukan pada tag hash #SQLHelp di Twitter tentang dampak rencana eksekusi pada jenis tunggu ASYNC_NETWORK_IO, dan hal itu menghasilkan beberapa pendapat berbeda dan banyak diskusi bagus.

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

Jawaban langsung saya untuk ini adalah bahwa seseorang salah menafsirkan sebab dan akibat dari ini, karena jenis tunggu ASYNC_NETWORK_IO ditemui ketika Mesin memiliki hasil untuk mengirim melalui TDS ke klien tetapi tidak ada buffer TDS yang tersedia pada koneksi untuk mengirimnya pada. Secara umum, ini berarti bahwa sisi klien tidak mengkonsumsi hasil secara efisien, tetapi berdasarkan diskusi berikutnya saya menjadi cukup tertarik untuk melakukan beberapa pengujian apakah rencana eksekusi benar-benar akan berdampak pada ASYNC_NETWORK_IO menunggu secara signifikan.

Untuk meringkas:Berfokus pada ASYNC_NETWORK_IO menunggu sendirian karena metrik penyetelan adalah kesalahan. Semakin cepat kueri dieksekusi, semakin tinggi jenis tunggu ini kemungkinan akan terakumulasi, bahkan jika klien mengonsumsi hasil secepat mungkin. (Juga lihat posting terbaru Greg tentang berfokus pada menunggu sendirian secara umum.)

Konfigurasi Uji

Untuk menjalankan tes ini, tabel yang sangat sederhana dibuat berdasarkan contoh yang diberikan kepada saya melalui email dari anggota komunitas lainnya, yang menunjukkan perubahan dalam tipe tunggu, tetapi juga memiliki kueri yang sama sekali berbeda di antara keduanya. tes dengan tabel tambahan yang digunakan dalam tes kedua, dan memiliki komentar untuk mematikan hasil, yang menghilangkan sebagian besar dari jenis tunggu ini untuk memulai, jadi ini bukan hanya perubahan rencana saja.

Catatan:Saya ingin menunjukkan bahwa ini sama sekali bukan pernyataan negatif terhadap siapa pun; diskusi berikutnya dan tes lebih lanjut yang berasal dari reproduksi asli yang disediakan sangat mendidik dan mengarah pada penelitian lebih lanjut untuk memahami tipe menunggu ini secara keseluruhan. Reproduksi asli DID menunjukkan perbedaan, tetapi dengan perubahan tambahan yang bukan merupakan bagian dari pertanyaan awal yang diajukan.

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

Menggunakan tabel ini sebagai kumpulan data dasar untuk menguji berbagai bentuk rencana menggunakan petunjuk, kueri berikut digunakan:

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;

Karena saya menjalankan kueri ini di SQL Server 2019 CU1, rencana eksekusi menyertakan informasi statistik tunggu aktual yang terkait dengan eksekusi kueri.

Catatan: Pengoptimal akan menggunakan Gabung Gabung tanpa petunjuk yang diterapkan untuk kumpulan data dan kueri khusus ini.

Hasil Tes Awal

Untuk pengujian awal saya hanya menggunakan SSMS untuk menjalankan kueri dan mengumpulkan rencana Eksekusi Aktual untuk membandingkan informasi tunggu yang terkait dengan setiap kueri yang ditunjukkan di bawah ini. Perhatikan bahwa untuk ukuran data ini, waktu yang berlalu tidak berbeda secara signifikan, begitu pula waktu tunggu atau jumlah tunggu untuk ASYNC_NETWORK_IO.

HAH GABUNG

<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" />

GABUNG GABUNG

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

LOOP GABUNG

<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" />

Namun, bukan di sini saya ingin menghentikan pengujian, karena pengalaman saya sendiri telah menunjukkan berulang kali bahwa Management Studio adalah konsumen hasil SQL Server yang sangat tidak efisien dan dapat dengan sendirinya menyebabkan ASYNC_NETWORK_IO menunggu untuk terjadi. Jadi, saya memutuskan untuk mengubah cara saya menguji berbagai hal dan beralih ke eksekusi kueri SQLCMD.

Menguji dengan SQLCMD

Karena saya banyak menggunakan SQLCMD untuk demo saat presentasi, saya membuat file testscript.sql dengan konten berikut:

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

Ini dieksekusi dari baris perintah sebagai berikut, dan selama penundaan 5 detik, jendela diminimalkan untuk memungkinkan eksekusi tidak merender dan menggulir hasil selama pemrosesan:

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

Untuk menangkap rencana eksekusi yang sebenarnya, saya pergi dengan sesi Acara yang Diperpanjang mengumpulkan acara query_post_execution_showplan yang, di belakang, pada SQL Server 2019 saya pikir saya seharusnya menggunakan query_post_execution_plan_profile alih-alih menggunakan implementasi statistik eksekusi kueri yang ringan membuat profil implementasi infrastruktur v3, tetapi acara ini tidak mengembalikan informasi WaitStats atau QueryTimeStats kecuali query_post_execution_showplan juga diaktifkan pada waktu yang sama. Selain itu, karena ini adalah mesin pengujian yang terisolasi tanpa beban kerja lain, dampak dari pembuatan profil standar tidak terlalu menjadi perhatian di sini.

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

HAH GABUNG

<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" />

GABUNG GABUNG

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

LOOP GABUNG

<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" />

Ini sebenarnya tidak berhasil menjadi cara yang lebih cepat untuk mengeksekusi kueri, dan kinerja sebenarnya berkurang dengan menggunakan utilitas baris perintah untuk mengeksekusi kueri, bahkan ketika jendela diperkecil dan tidak terlihat menggulir hasilnya. Dengan jendela terbuka, waktu eksekusi HASH adalah 15708 md dan waktu tunggu ASYNC_NETWORK_IO adalah 15126 md. Namun, ini menunjukkan bahwa untuk hasil yang sama persis, kinerja klien yang menggunakan hasil memengaruhi waktu tunggu dan waktu eksekusi kueri.

Dampak Paralelisme?

Salah satu hal yang saya perhatikan adalah bahwa hanya dua dari rencana telah dieksekusi dengan paralelisme, berdasarkan keberadaan CXPACKET dan LATCH_EX menunggu dalam rencana eksekusi XML. Jadi saya bertanya-tanya seperti apa dampak memaksa rencana eksekusi serial terhadap eksekusi kueri yang sama ini menggunakan OPTION (MAXDOP 1).

HAH GABUNG

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

GABUNG GABUNG

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

LOOP GABUNG

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

Perhatikan di sini bahwa jumlah tunggu keseluruhan tidak berkurang secara signifikan. Hanya paket bergabung loop serial yang memiliki perubahan besar dalam jumlah menunggu atau jumlah total waktu tunggu yang terkait dengannya, dan secara terpisah ini tidak berarti bahwa itu adalah manfaat positif, waktu eksekusi untuk kueri tidak meningkat secara signifikan dan mungkin ada faktor lain yang mempengaruhi hasil tes khusus itu.

Tabel di bawah ini meringkas waktu tunggu dan hitungan ASYNC_NETWORK_IO untuk setiap pengujian.

PlanType Baris Hitungan Tunggu Waktu Tunggu ExecTime Nama Aplikasi MAXDOP 1 Paralel
Hash 250.000 6.635 4,394 4,961 SSMS N Y
Gabung 250.000 6,592 3,169 3,933 SSMS N N
Putaran 250.000 6.631 3,576 4.084 SSMS N Y
Hash 250.000 6.610 11.321 11,874 SQLCMD N Y
Gabung 250.000 6.602 10.837 11.597 SQLCMD N N
Putaran 250.000 6.612 11.177 11.696 SQLCMD N Y
Hash 250.000 6,379 4.047 4,619 SSMS Y N
Gabung 250.000 6.608 3,699 4,479 SSMS Y N
Putaran 250.000 5.385 2.083 3,918 SSMS Y N

Ringkasan

Meskipun investigasi postingan ini tidak mencakup setiap aspek dari perubahan paket atau jenis tunggu ASYNC_NETWORK_IO, ini menunjukkan bahwa menunggu ini tidak dipengaruhi secara signifikan oleh rencana eksekusi yang digunakan untuk eksekusi kueri. Saya akan mengklasifikasikan tipe menunggu ini hampir seperti tipe menunggu CXPACKET ketika melakukan analisis server secara keseluruhan; normal untuk melihat sebagian besar beban kerja dan kecuali jika sangat miring dan ada masalah kinerja lain yang menunjukkan konsumsi hasil yang lambat oleh klien seperti memblokir dengan pemblokir utama menunggu ASYNC_NETWORK_IO, maka sesuatu yang harus diabaikan hanya sebagai 'bagian dari tanda tangan menunggu normal untuk beban kerja'.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Temukan Kebocoran Koneksi Database di Aplikasi Anda

  2. Cara menghitung usia dari tanggal lahir di SQL

  3. SQL DELETE untuk Pemula

  4. Cara Menambahkan Posisi Peringkat Baris dalam SQL dengan RANK()

  5. Menggunakan DBCC CLOENDATABASE dan Query Store untuk Pengujian