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

Statistik Penantian Lutut :PAGEIOLATCH_SH

Dalam posting saya tahun ini, saya telah membahas reaksi spontan terhadap berbagai jenis menunggu, dan dalam posting ini saya akan melanjutkan dengan tema statistik menunggu dan membahas PAGEIOLATCH_XX tunggu. Saya katakan "tunggu" tetapi sebenarnya ada beberapa jenis PAGEIOLATCH tunggu, yang saya tandai dengan XX di akhir. Contoh paling umum adalah:

  • PAGEIOLATCH_SH – (SH are) menunggu halaman file data dibawa dari disk ke buffer pool sehingga isinya dapat dibaca
  • PAGEIOLATCH_EX atau PAGEIOLATCH_UP – (EX eksklusif atau UP date) menunggu halaman file data dibawa dari disk ke buffer pool sehingga isinya dapat dimodifikasi

Dari jumlah tersebut, sejauh ini jenis yang paling umum adalah PAGEIOLATCH_SH .

Ketika tipe menunggu ini adalah yang paling umum di server, reaksi spontannya adalah bahwa subsistem I/O pasti memiliki masalah dan di situlah penyelidikan harus difokuskan.

Hal pertama yang harus dilakukan adalah membandingkan PAGEIOLATCH_SH menunggu hitungan dan durasi terhadap baseline Anda. Jika volume menunggu kurang lebih sama, tetapi durasi setiap menunggu baca menjadi lebih lama, maka saya akan khawatir tentang masalah subsistem I/O, seperti:

  • Kesalahan konfigurasi/malfungsi pada tingkat subsistem I/O
  • Latensi jaringan
  • Beban kerja I/O lain yang menyebabkan perselisihan dengan beban kerja kami
  • Konfigurasi replikasi/pencerminan subsistem I/O sinkron

Dalam pengalaman saya, polanya sering kali jumlah PAGEIOLATCH_SH menunggu telah meningkat secara substansial dari jumlah dasar (normal) dan durasi menunggu juga meningkat (yaitu waktu untuk membaca I/O telah meningkat), karena jumlah besar membaca membebani subsistem I/O. Ini bukan masalah subsistem I/O – ini adalah SQL Server yang mendorong lebih banyak I/O dari yang seharusnya. Fokus sekarang perlu beralih ke SQL Server untuk mengidentifikasi penyebab I/O tambahan.

Penyebab Banyaknya I/Os Baca

SQL Server memiliki dua jenis pembacaan:I/O logis dan I/O fisik. Ketika bagian Access Methods dari Storage Engine perlu mengakses halaman, ia meminta Buffer Pool untuk penunjuk ke halaman dalam memori (disebut I/O logis) dan Buffer Pool memeriksa metadatanya untuk melihat apakah halaman itu sudah ada di memori.

Jika halaman berada dalam memori, Buffer Pool memberikan pointer pada Access Methods, dan I/O tetap menjadi I/O logis. Jika halaman tidak ada dalam memori, Buffer Pool mengeluarkan I/O "nyata" (disebut I/O fisik) dan utas harus menunggu hingga selesai – menimbulkan PAGEIOLATCH_XX tunggu. Setelah I/O selesai dan penunjuk tersedia, utas diberi tahu dan dapat terus berjalan.

Di dunia yang ideal, seluruh beban kerja Anda akan muat dalam memori dan begitu kumpulan buffer telah "memanas" dan menampung semua beban kerja, tidak perlu lagi membaca, hanya menulis data yang diperbarui. Ini bukan dunia yang ideal, dan sebagian besar dari Anda tidak memiliki kemewahan itu, jadi beberapa bacaan tidak bisa dihindari. Selama jumlah bacaan tetap di sekitar jumlah dasar Anda, tidak ada masalah.

Saat sejumlah besar pembacaan diperlukan secara tiba-tiba dan tidak terduga, itu pertanda bahwa ada perubahan signifikan baik dalam beban kerja, jumlah memori kumpulan buffer yang tersedia untuk menyimpan salinan halaman dalam memori, atau keduanya.

Berikut adalah beberapa kemungkinan penyebab utama (bukan daftar lengkap):

  • Tekanan memori Windows eksternal pada SQL Server menyebabkan manajer memori mengurangi ukuran kumpulan buffer
  • Rencanakan cache bloat yang menyebabkan memori ekstra dipinjam dari kumpulan buffer
  • Rencana kueri melakukan pemindaian tabel/indeks berkerumun (bukan pencarian indeks) karena:
    • peningkatan volume beban kerja
    • masalah mengendus parameter
    • indeks nonclustered wajib yang dijatuhkan atau diubah
    • konversi implisit

Satu pola yang harus dicari yang akan menyarankan pemindaian tabel/indeks berkerumun menjadi penyebabnya juga melihat sejumlah besar CXPACKET menunggu bersama dengan PAGEIOLATCH_SH menunggu. Ini adalah pola umum yang menunjukkan terjadinya pemindaian tabel paralel/indeks berkerumun yang besar.

Dalam semua kasus, Anda dapat melihat rencana kueri apa yang menyebabkan PAGEIOLATCH_SH menunggu menggunakan sys.dm_os_waiting_tasks dan DMV lainnya, dan Anda bisa mendapatkan kode untuk melakukannya di posting blog saya di sini. Jika Anda memiliki alat pemantauan pihak ketiga yang tersedia, alat ini mungkin dapat membantu Anda mengidentifikasi pelakunya tanpa membuat tangan Anda kotor.

Contoh Alur Kerja dengan SQL Sentry dan Plan Explorer

Dalam contoh sederhana (jelas dibuat-buat), mari kita asumsikan bahwa saya menggunakan sistem klien menggunakan rangkaian alat SQL Sentry dan melihat lonjakan I/O menunggu di tampilan dasbor SQL Sentry, seperti yang ditunjukkan di bawah ini:


Melihat lonjakan I/O menunggu di SQL Sentry

Saya memutuskan untuk menyelidiki dengan mengklik kanan interval waktu yang dipilih di sekitar waktu lonjakan, lalu melompat ke tampilan Top SQL, yang akan menunjukkan kepada saya kueri paling mahal yang telah dieksekusi:


Menyoroti rentang waktu dan menavigasi ke SQL Teratas

Dalam tampilan ini, saya dapat melihat kueri I/O yang berjalan lama atau tinggi mana yang berjalan pada saat lonjakan terjadi, dan kemudian memilih untuk menelusuri rencana kueri mereka (dalam hal ini, hanya ada satu kueri yang berjalan lama, yang berlangsung hampir satu menit):


Meninjau kueri yang berjalan lama di SQL Teratas

Jika saya melihat paket di klien SQL Sentry atau membukanya di SQL Sentry Plan Explorer, saya langsung melihat banyak masalah. Jumlah pembacaan yang diperlukan untuk mengembalikan 7 baris tampaknya terlalu tinggi, delta antara baris yang diperkirakan dan yang sebenarnya besar, dan rencana menunjukkan pemindaian indeks yang terjadi di tempat yang saya harapkan:


Melihat peringatan konversi implisit dalam rencana kueri

Penyebab semua ini disorot dalam peringatan di SELECT operator:Ini adalah konversi implisit!

Konversi implisit adalah masalah berbahaya yang disebabkan oleh ketidakcocokan antara tipe data predikat pencarian dan tipe data kolom yang dicari, atau perhitungan yang dilakukan pada kolom tabel daripada predikat pencarian. Dalam kedua kasus tersebut, SQL Server tidak dapat menggunakan pencarian indeks pada kolom tabel dan harus menggunakan pemindaian sebagai gantinya.

Ini dapat muncul dalam kode yang tampaknya tidak bersalah, dan contoh umum adalah menggunakan perhitungan tanggal. Jika Anda memiliki tabel yang menyimpan usia pelanggan, dan Anda ingin melakukan perhitungan untuk melihat berapa banyak yang berusia 21 tahun atau lebih hari ini, Anda dapat menulis kode seperti ini:

WHERE DATEADD (YEAR, 21, [MyTable].[BirthDate]) <= @today;

Dengan kode ini, kalkulasi berada di kolom tabel sehingga pencarian indeks tidak dapat digunakan, menghasilkan ekspresi yang tidak dapat dicari (secara teknis dikenal sebagai ekspresi non-SARGable) dan pemindaian tabel/indeks berkerumun. Ini dapat diselesaikan dengan memindahkan perhitungan ke sisi lain dari operator:

WHERE [MyTable].[BirthDate] <= DATEADD (YEAR, -21, @today);

Dalam hal ketika perbandingan kolom dasar memerlukan konversi tipe data yang dapat menyebabkan konversi implisit, rekan saya Jonathan Kehayias menulis posting blog yang sangat baik yang membandingkan setiap kombinasi tipe data dan catatan ketika konversi implisit akan diperlukan.

Ringkasan

Jangan terjebak dengan pemikiran yang berlebihan PAGEIOLATCH_XX menunggu disebabkan oleh subsistem I/O. Dalam pengalaman saya, mereka biasanya disebabkan oleh sesuatu yang berkaitan dengan SQL Server dan di situlah saya akan mulai memecahkan masalah.

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
  • Pengawal SQL

Pada artikel berikutnya dalam seri ini, saya akan membahas tipe menunggu lain yang merupakan penyebab umum reaksi spontan. Sampai saat itu, selamat memecahkan masalah!


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Menggunakan Jenkins dengan Kubernetes AWS, Bagian 3

  2. Tips untuk Baca/Tulis Kunci Tergantung pada Tingkat Isolasi Transaksi di MSSQL

  3. Cara Menginstal Apache Cassandra Di Ubuntu 20.10/Ubuntu 20.04

  4. Alasan Lain untuk Menghindari sp_updatestats

  5. Menggunakan DBCC CLOENDATABASE dan Query Store untuk Pengujian