Selama 18 bulan terakhir saya telah berfokus pada reaksi spontan untuk menunggu analisis statistik dan topik terkait penyesuaian kinerja lainnya, dan dalam posting ini saya akan melanjutkannya dan membahas PAGELATCH_XX menunggu. XX di akhir penantian berarti ada beberapa jenis PAGELATCH tunggu, dan contoh yang paling umum adalah:
- PAGELATCH_SH – ( SH are) menunggu akses ke halaman file data di memori sehingga konten halaman dapat dibaca
- PAGELATCH_EX atau PAGELATCH_UP – (EX eksklusif atau UP date) menunggu akses ke halaman file data di memori sehingga konten halaman dapat dimodifikasi
Ketika salah satu dari jenis menunggu ini adalah yang paling umum di server, reaksi spontan adalah bahwa masalahnya ada hubungannya dengan I/O (yaitu kebingungan dengan PAGEIOLATCH_XX tipe tunggu, yang saya bahas dalam posting pada tahun 2014) dan seseorang mencoba menambahkan lebih banyak memori atau mengubah subsistem I/O. Tak satu pun dari reaksi ini akan berpengaruh sama sekali, karena halaman file data yang sedang diperebutkan sudah ada di memori di buffer pool!
Dalam semua kasus, Anda dapat melihat apakah Anda memiliki masalah dengan PAGELATCH_XX pertengkaran menggunakan sys.dm_os_waiting_tasks script di blog saya atau menggunakan alat seperti Performance Advisor, seperti yang ditunjukkan (untuk jenis tunggu yang berbeda) dalam posting ini.
Jadi apa sumber pertengkarannya? Pertama saya akan menjelaskan latar belakang di balik jenis menunggu ini, lalu saya akan membahas dua penyebab paling umum dari PAGELATCH_XX pertengkaran.
Latar Belakang:Kait
Sebelum saya membahas beberapa penyebab PAGELATCH_XX tunggu, saya ingin menjelaskan mengapa mereka ada.
Dalam sistem multi-utas apa pun, struktur data yang dapat diakses dan dimanipulasi oleh banyak utas perlu dilindungi untuk mencegah skenario seperti:
- Dua utas memperbarui struktur data secara bersamaan, dan beberapa pembaruan hilang
- Sebuah utas memperbarui struktur data secara bersamaan dengan utas lain yang membaca struktur data, sehingga utas membaca melihat campuran data lama dan baru
Ini adalah ilmu komputer dasar, dan SQL Server tidak berbeda, jadi semua struktur data di dalam SQL Server harus memiliki kontrol akses multi-utas.
Salah satu mekanisme yang digunakan SQL Server untuk melakukan ini disebut latch, di mana menahan latch dalam mode eksklusif mencegah utas lain mengakses struktur data, dan menahan latch dalam mode berbagi mencegah utas lain mengubah struktur data. SQL Server juga menggunakan spinlocks untuk beberapa struktur data dan saya membahasnya di postingan ini pada tahun 2014.
Tetapi mengapa halaman file data di memori dilindungi oleh kait, Anda mungkin bertanya-tanya? Yah, halaman file data hanyalah sebuah struktur data, meskipun memiliki tujuan khusus, dan karenanya memerlukan kontrol akses yang sama seperti struktur data lainnya. Jadi, ketika satu utas perlu memodifikasi halaman file data, ia perlu memperoleh kait eksklusif atau pembaruan pada halaman, dan jika tidak dapat dan perlu menunggu, ketik wait PAGELATCH_EX atau PAGELATCH_UP hasil.
Pertentangan tempdb klasik
PAGELATCH pertengkaran di tempdb biasanya pada bitmap alokasi dan terjadi dengan beban kerja dengan banyak koneksi bersamaan yang membuat dan menjatuhkan tabel sementara kecil (yang disimpan di tempdb).
Ketika baris pertama dimasukkan ke dalam tabel sementara, dua halaman harus dialokasikan (halaman data dan halaman IAM, yang melacak halaman data). Halaman-halaman ini perlu ditandai sebagai dialokasikan di halaman alokasi khusus yang disebut halaman PFS, dan secara default dialokasikan dari ekstensi data khusus yang dilacak oleh halaman alokasi lain yang disebut halaman SGAM (detailnya dapat ditemukan di posting blog lama saya di sini). Saat tabel sementara dijatuhkan, halaman ini perlu dialokasikan kembali, yang memerlukan lebih banyak perubahan pada halaman PFS dan SGAM.
Jika tabel sementara kecil, dan ukuran kumulatif dari semua tabel sementara yang dibuat secara bersamaan kurang dari 64 MB, maka semua perubahan bitmap alokasi ini dipusatkan pada halaman PFS dan SGAM pertama di file data tempdb (dengan ID halaman (1:1) dan (1:3) masing-masing). Memperbarui salah satu halaman alokasi ini memerlukan penguncian halaman, dan hanya satu utas pada satu waktu yang dapat mengubah halaman, jadi semua utas lainnya harus menunggu – dengan jenis tunggu PAGELATCH_UP .
Dari SQL Server 2005 dan seterusnya, tabel sementara dapat di-cache saat dijatuhkan, selama ukurannya kurang dari 8 MB (dan di SQL Server 2014 tidak dibuat dalam prosedur tersimpan yang juga memiliki pernyataan DDL di tabel sementara). Ini berarti bahwa utas berikutnya yang menjalankan rencana kueri yang sama dapat mengeluarkan tabel sementara dari cache dan tidak harus berurusan dengan alokasi awal. Ini mengurangi pertengkaran pada bitmap alokasi, tetapi cache tabel sementara tidak terlalu besar, sehingga beban kerja dengan ratusan pembuatan/penurunan tabel sementara secara bersamaan masih akan melihat banyak pertentangan.
Sangat sepele untuk mencegah pertikaian pada halaman SGAM di tempdb dengan mengaktifkan tanda jejak terdokumentasi 1118 di server, yang menurut saya harus diaktifkan di semua server di seluruh dunia, dan sebenarnya merupakan perilaku default yang tidak dapat diubah di SQL Server 2016.
Mencegah pertikaian pada halaman PFS di tempdb sedikit lebih sulit. Dengan asumsi bahwa tabel sementara diperlukan untuk kinerja, triknya adalah memiliki beberapa file data untuk tempdb sehingga alokasi dilakukan secara round-robin di antara file-file tersebut, pertikaian dibagi menjadi beberapa halaman PFS, sehingga keseluruhan pertentangan turun. Sayangnya, tidak ada jawaban yang tepat untuk berapa banyak file data yang seharusnya Anda miliki. Anda dapat membaca lebih lanjut tentang panduan yang diterima secara umum tentang ini di artikel KB 2154845 dan di entri blog ini.
Sisipkan Hotspot
Dalam basis data pengguna, penyebab umum tingginya jumlah PAGELATCH_EX menunggu adalah hotspot penyisipan.
Hal ini dapat terjadi bila tabel memiliki indeks kluster dengan kunci kluster int atau bigint, dan ukuran baris yang cukup kecil sehingga puluhan atau lebih baris tabel dapat ditampung pada halaman data pada tingkat daun indeks kluster.
Untuk tabel seperti itu, jika beban kerja melibatkan puluhan atau ratusan utas bersamaan yang dimasukkan ke dalam tabel, banyak utas akan menghasilkan baris dengan nilai identitas (dan karenanya kunci cluster) yang perlu dimasukkan ke halaman data tingkat daun yang sama .
Sekarang ingat bahwa membuat perubahan apa pun ke halaman file data di memori memerlukan kait eksklusif, jadi setiap utas yang mencoba menyisipkan ke halaman yang sama harus mendapatkan kait halaman secara eksklusif. Saat setiap utas memegang kait eksklusif, utas lainnya akan menunggu PAGELATCH_EX untuk halaman itu, pada dasarnya membuat penyisipan bersamaan menjadi proses sinkron yang sangat terhambat.
Ada beberapa kemungkinan perbaikan untuk masalah ini:
- Gunakan kunci yang lebih acak, dan ketahui bahwa ini akan menyebabkan fragmentasi indeks, jadi gunakan juga faktor pengisian indeks untuk membantu mencegah pemisahan halaman
- Sebarkan sisipan di tabel menggunakan semacam mekanisme partisi buatan
- Gunakan ukuran baris tabel yang lebih panjang (ini jelas merupakan opsi yang paling tidak cocok)
Saya telah melihat hotspot penyisipan seperti ini muncul ketika seseorang mencoba menghapus masalah fragmentasi indeks dengan mengubah kunci kluster GUID acak menjadi kunci kluster identitas int atau bigint, tetapi gagal menguji skema tabel baru di bawah beban produksi.
Ringkasan
Sama seperti jenis menunggu lainnya, memahami dengan tepat apa PAGELATCH_XX menunggu mean adalah kunci untuk memahami bagaimana memecahkan masalah mereka.
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
Sampai jumpa lagi, selamat memecahkan masalah!