Dalam beberapa posting saya selama setahun terakhir, saya telah menggunakan tema orang-orang yang melihat tipe penantian tertentu dan kemudian bereaksi dengan cara yang “sentuhan” terhadap penantian yang ada di sana. Biasanya ini berarti mengikuti beberapa saran Internet yang buruk dan mengambil tindakan drastis yang tidak pantas atau mengambil kesimpulan tentang akar penyebab masalah, lalu membuang waktu dan tenaga untuk mengejarnya.
Salah satu jenis menunggu di mana reaksi spontan paling kuat, dan di mana beberapa saran paling buruk ada, adalah CXPACKET menunggu. Ini juga jenis menunggu yang paling sering menunggu di server orang (menurut dua survei besar jenis menunggu saya dari 2010 dan 2014 – lihat di sini untuk detailnya), jadi saya akan membahasnya di posting ini.
Apa yang dimaksud dengan tipe menunggu CXPACKET?
Penjelasan paling sederhana adalah bahwa CXPACKET berarti Anda memiliki kueri yang berjalan secara paralel dan Anda akan *selalu* melihat CXPACKET menunggu kueri paralel. CXPACKET menunggu TIDAK berarti Anda memiliki paralelisme yang bermasalah – Anda perlu menggali lebih dalam untuk menentukannya.
Sebagai contoh operator paralel, pertimbangkan operator Repartition Streams, yang memiliki ikon berikut dalam paket kueri grafis:
Dan inilah gambar yang menunjukkan apa yang terjadi dalam hal utas paralel untuk operator ini, dengan derajat paralelisme (DOP) sama dengan 4:
Untuk DOP =4, akan ada empat utas produsen, menarik data dari sebelumnya dalam rencana kueri, data kemudian kembali ke sisa rencana kueri melalui empat utas konsumen.
Anda dapat melihat berbagai utas di operator paralel yang menunggu sumber daya menggunakan sys.dm_os_waiting_tasks DMV, di exec_context_id kolom (postingan ini memiliki skrip saya untuk melakukan ini).
Selalu ada utas 'kontrol' untuk rencana paralel apa pun, yang secara tidak sengaja selalu menjadi utas ID 0. Utas kontrol selalu mencatat CXPACKET menunggu, dengan durasi yang sama dengan lama waktu yang dibutuhkan rencana untuk dieksekusi. Paul White memiliki penjelasan yang bagus tentang utas dalam rencana paralel di sini.
Satu-satunya waktu utas non-kontrol akan mendaftarkan CXPACKET menunggu adalah jika mereka selesai sebelum utas lainnya di operator. Ini dapat terjadi jika salah satu utas macet menunggu sumber daya untuk waktu yang lama, jadi lihatlah jenis tunggu dari utas yang tidak menampilkan CXPACKET (menggunakan skrip saya di atas) dan pecahkan masalah dengan tepat. Ini juga dapat terjadi karena distribusi pekerjaan yang tidak seimbang di antara utas, dan saya akan membahas lebih dalam tentang kasus itu di posting saya berikutnya di sini (ini disebabkan oleh statistik kedaluwarsa dan masalah estimasi kardinalitas lainnya).
Perhatikan bahwa di SQL Server 2016 SP2 dan SQL Server 2017 RTM CU3, utas konsumen tidak lagi mendaftar CXPACKET menunggu. Mereka mendaftarkan CXCONSUMER menunggu, yang jinak dan dapat diabaikan. Ini untuk mengurangi jumlah menunggu CXPACKET yang dihasilkan, dan yang tersisa lebih mungkin untuk ditindaklanjuti.
Paralelisme tak terduga?
Mengingat bahwa CXPACKET berarti Anda mengalami paralelisme, hal pertama yang harus dilihat adalah apakah Anda mengharapkan paralelisme untuk kueri yang menggunakannya. Kueri saya akan memberi Anda ID node paket kueri tempat paralelisme terjadi (itu mengeluarkan ID node dari paket kueri XML jika tipe tunggu dari utasnya adalah CXPACKET) jadi cari ID node itu dan tentukan apakah paralelisme masuk akal .
Salah satu kasus umum paralelisme tak terduga adalah ketika pemindaian tabel terjadi di mana Anda mengharapkan pencarian atau pemindaian indeks yang lebih kecil. Anda akan melihat ini dalam rencana kueri atau Anda akan melihat banyak PAGEIOLATCH_SH menunggu (dibahas secara rinci di sini) bersama dengan CXPACKET menunggu (pola statistik menunggu klasik yang harus diwaspadai). Ada berbagai penyebab pemindaian tabel yang tidak terduga, termasuk:
- Indeks nonclustered tidak ada sehingga pemindaian tabel adalah satu-satunya alternatif
- Statistik kedaluwarsa sehingga Pengoptimal Kueri menganggap pemindaian tabel adalah metode akses data terbaik untuk digunakan
- Konversi implisit, karena ketidakcocokan tipe data antara kolom tabel dan variabel atau parameter, yang berarti indeks nonclustered tidak dapat digunakan
- Aritmatika dilakukan pada kolom tabel alih-alih variabel atau parameter, yang berarti indeks nonclustered tidak dapat digunakan
Dalam semua kasus ini, solusinya ditentukan oleh apa yang Anda temukan sebagai akar masalahnya.
Tetapi bagaimana jika tidak ada kasus akar yang jelas dan kueri dianggap cukup mahal untuk menjamin paket paralel?
Mencegah paralelisme
Antara lain, Pengoptimal Kueri memutuskan untuk membuat paket kueri paralel jika paket serial memiliki biaya yang lebih tinggi daripada cost threshold for parallelism
, pengaturan sp_configure untuk instance. Ambang biaya untuk paralelisme (atau CTFP) ditetapkan ke lima secara default, yang berarti bahwa paket tidak harus sangat mahal untuk memicu pembuatan paket paralel.
Salah satu cara termudah untuk mencegah paralelisme yang tidak diinginkan adalah dengan meningkatkan CTFP ke angka yang jauh lebih tinggi, dengan semakin tinggi Anda mengaturnya, semakin kecil kemungkinan rencana paralel akan dibuat. Beberapa orang menganjurkan pengaturan CTFP ke suatu tempat antara 25 dan 50, tetapi seperti semua pengaturan yang dapat diubah, yang terbaik adalah menguji berbagai nilai dan melihat apa yang terbaik untuk lingkungan Anda. Jika Anda ingin sedikit lebih banyak metode terprogram untuk membantu memilih nilai CTFP yang baik, Jonathan menulis posting blog yang menunjukkan kueri untuk menganalisis cache rencana dan menghasilkan nilai yang disarankan untuk CTFP. Sebagai contoh, kami memiliki satu klien dengan CTFP yang disetel ke 200, dan yang lainnya disetel ke maksimum – 32767 – sebagai cara untuk mencegah paralelisme apa pun secara paksa.
Anda mungkin bertanya-tanya mengapa klien kedua harus menggunakan CTFP sebagai metode palu godam untuk mencegah paralelisme ketika Anda mengira mereka dapat dengan mudah mengatur server 'tingkat paralelisme maksimum' (atau MAXDOP) ke 1. Nah, siapa pun dengan tingkat izin apa pun dapat tentukan petunjuk MAXDOP kueri dan ganti setelan MAXDOP server, tetapi CTFP tidak dapat diganti.
Dan itu adalah metode lain untuk membatasi paralelisme – menyetel petunjuk MAXDOP pada kueri yang tidak ingin Anda paralelkan.
Anda juga dapat menurunkan pengaturan MAXDOP server, tetapi itu adalah solusi drastis karena dapat mencegah semuanya menggunakan paralelisme. Saat ini sudah umum bagi server untuk memiliki beban kerja yang beragam, misalnya dengan beberapa kueri OLTP dan beberapa kueri pelaporan. Jika Anda menurunkan server MAXDOP, kinerja kueri pelaporan akan tertatih-tatih.
Solusi yang lebih baik ketika ada beban kerja campuran adalah menggunakan CTFP seperti yang saya jelaskan di atas atau menggunakan Resource Governor (saya khawatir hanya untuk perusahaan). Anda dapat menggunakan Resource Governor untuk memisahkan beban kerja ke dalam grup beban kerja, lalu menetapkan MAX_DOP (garis bawah bukan salah ketik) untuk setiap grup beban kerja. Dan hal yang baik tentang menggunakan Resource Governor adalah MAX_DOP tidak dapat ditimpa oleh petunjuk kueri MAXDOP.
Ringkasan
Jangan jatuh ke dalam perangkap berpikir bahwa CXPACKET menunggu secara otomatis berarti Anda mengalami paralelisme yang buruk, dan tentu saja jangan ikuti beberapa saran Internet yang pernah saya lihat tentang membanting server dengan mengatur MAXDOP ke 1. Luangkan waktu untuk menyelidiki mengapa Anda melihat CXPACKET menunggu dan apakah itu sesuatu yang harus ditangani atau hanya artefak dari beban kerja yang berjalan dengan benar.
Sejauh menyangkut statistik tunggu umum, Anda dapat menemukan informasi lebih lanjut tentang menggunakannya untuk pemecahan masalah kinerja di:
- Seri posting blog SQLskills saya, dimulai dengan statistik Tunggu, atau tolong beri tahu saya di bagian mana yang sakit
- Perpustakaan Jenis Tunggu dan Kelas Latch Saya di sini
- Kursus pelatihan online Pluralsight saya SQL Server:Pemecahan Masalah Kinerja Menggunakan Statistik Tunggu
- Penasihat Kinerja SQL Sentry
Dalam artikel berikutnya dalam seri ini, saya akan membahas paralelisme miring dan memberi Anda cara sederhana untuk melihatnya terjadi. Sampai saat itu, selamat memecahkan masalah!