Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

Memecahkan masalah kueri yang berjalan lama di MS SQL Server

Pengantar

Ada sistem informasi yang saya kelola. Sistem ini terdiri dari komponen-komponen berikut:

1. Basis data MS SQL Server
2. Aplikasi server
3. Aplikasi klien

Sistem informasi ini diinstal pada beberapa objek. Sistem informasi digunakan secara aktif 24 jam sehari oleh 2 hingga 20 pengguna sekaligus pada setiap objek. Oleh karena itu, Anda tidak dapat melakukan perawatan rutin sekaligus. Jadi, saya harus «menyebarkan» defragmentasi indeks SQL Server sepanjang hari, daripada mendefrag semua indeks terfragmentasi yang diperlukan sekaligus. Ini juga berlaku untuk operasi lain.

Properti pembaruan otomatis statistik diatur dalam properti database. Selain itu, statistik diperbarui pada indeks yang didefrag.

Masalah

Sekitar setahun yang lalu, saya mengalami masalah berikut:

Dari waktu ke waktu, semua kueri berjalan lambat. Khususnya, waktu tunda itu acak. Itu terjadi pada setiap objek pada hari yang acak. Terlebih lagi, ketika saya mulai menganalisis seberapa sering penundaan terjadi (menggunakan profiler), saya menemukan bahwa penundaan itu terjadi setiap hari pada waktu yang acak. Pengguna tidak selalu memperhatikannya tetapi menganggapnya sebagai satu-satunya penundaan acak, dan kemudian sistem bekerja kembali dengan cepat.

Memecahkan masalah

Saya telah meninjau semua kueri yang berjalan lambat. Hal yang paling aneh adalah semua kueri berjalan lambat pada waktu yang acak, bahkan yang paling sederhana, seperti menarik catatan terakhir dari tabel dengan beberapa ribu baris.

Selanjutnya, saya melakukan langkah-langkah berikut:

1. Saya menganalisis log MS SQL Server dan Windows Server, tetapi tidak dapat menemukan penyebab penundaan.
2. Saya menganalisis indeks (fragmentasi, dll.), menambahkan yang hilang dan menghapus yang tidak digunakan.
3. Saya menganalisis kueri – beberapa kueri ditingkatkan.
4. Saya menganalisis tugas di Agen SQL dan tidak dapat mengaitkan tugas dengan masalah penundaan.
5. Saya menganalisis tugas di Penjadwal Tugas dan tidak dapat mengaitkan tugas dengan masalah penundaan.
6. Profiler menunjukkan hasil, tetapi bukan penyebab keterlambatan.
7. Saya melakukan pemeriksaan kebuntuan – tidak ada pemblokiran panjang yang terungkap.

Akibatnya, saya menghabiskan lebih dari 3 bulan untuk pencarian yang gagal tentang alasan kueri yang berjalan lambat sesekali. Namun, saya mengungkapkan fakta menarik — alih-alih indikator eksekusi Worker, indikator Elapsed wait meningkat untuk semua kueri. Fakta ini memberi saya ide bahwa ada sesuatu yang salah dengan disk. Saya memeriksanya – semuanya baik-baik saja.

Solusi

Yang mengejutkan saya, saya secara tidak sengaja mengungkapkan bahwa ketika kueri dijalankan dengan lambat di aplikasi, kueri itu berjalan dengan cepat di SSMS. Satu artikel membantu dalam memecahkan masalah (setidaknya itu menyarankan ide).

Sebuah paragraf dari artikel:

Dalam praktiknya, opsi SET yang paling penting adalah ARITHABORT, karena nilai default untuk opsi ini berbeda untuk aplikasi dan SQL Server Management Studio. Ini menjelaskan mengapa Anda bisa mendeteksi kueri yang berjalan lambat di aplikasi Anda, lalu mendapatkan kecepatan yang baik dengan menjalankannya di SSMS. Aplikasi menggunakan rencana yang dibuat untuk sekumpulan nilai yang berbeda dari nilai sebenarnya yang benar. Sedangkan jika Anda menjalankan kueri di SSMS, kemungkinan besar cache belum memiliki rencana eksekusi untuk ARITHABORT ON, dan oleh karena itu SQL Server akan membuat rencana untuk nilai Anda saat ini.

Perbedaan eksekusi disebabkan oleh parameter SET ARITHABORT. Untuk semua kueri yang dieksekusi di SSMS, opsi ini diaktifkan, dan untuk kueri dari luar (dari aplikasi) – dinonaktifkan. Itu tidak dapat diaktifkan bahkan dengan permintaan sederhana untuk aplikasi:

SET ARITHABORT ON;

Sebuah ide gila mengikuti – membersihkan cache prosedural pada saat hangup.

Untuk pemeriksaan manual selanjutnya, saya perlu menulis pernyataan berikut sebelum kueri di SSMS:

SET ARITHABORT OFF;

Dengan demikian kami akan mensimulasikan pengoperasian aplikasi. Ketika kueri telah berjalan lama, saya membersihkan cache prosedural. Dan ini selalu membantu. Sebelum mengosongkan cache prosedural, kueri dapat berjalan hingga 20-30 detik, dan setelahnya – 0 detik.

Setelah itu, saya melakukan percobaan lain – membersihkan seluruh cache prosedural untuk seluruh database setiap jam melalui SQL Agent:

--cleaning the cache by database id
DBCC FLUSHPROCINDB (@db_id);

Setelah itu, semua kueri berjalan sangat cepat (kurang dari 0,05 detik). Hanya ada beberapa kemunculan hingga 5-10 detik eksekusi, tetapi pengguna tidak melihat adanya hangup. Selain itu, memperbarui statistik tidak meningkatkan hasil, jadi saya menonaktifkan pembaruan statistik.

Setelah beberapa bulan belajar, saya menemukan bahwa hangup sesekali terjadi ketika cache menghabiskan semua yang ada di server, dan tidak ada ruang kosong yang tersisa atau ada memori kosong, tetapi RAM kurang dari 1 GB atau layanan MS SQL Server menempati semua RAM yang dialokasikan (melalui Task Manager). Tetapi peristiwa kedua hanya terjadi dua kali per seluruh penelitian.

Faktanya adalah bahwa secara harfiah semuanya ditulis ke dalam cache, sementara cache tidak selalu dirilis tepat waktu. Masalah dengan cache diselesaikan menggunakan program EmptyStandbyList.exe.

Saya mengonfigurasi aplikasi ini melalui Penjadwal Tugas untuk dijalankan 1 kali setiap jam. Setelah semua pekerjaan selesai, tidak ada penghentian kueri pada semua objek selama lebih dari setengah tahun sekarang.

Satu-satunya hal yang masih belum jelas adalah kasus yang jarang terjadi ketika satu kueri hangup selama 5-10 detik sebulan sekali pada hari yang acak dan pada waktu yang acak. Ada 4 kasus seperti itu dan hanya pada dua objek selama setengah tahun ketika layanan MS SQL Server menempati semua memori yang dialokasikan untuk periode waktu yang singkat.

Pada dasarnya, tidak perlu menggali lebih dalam, karena pengguna tidak melihat adanya hangup dan semuanya berfungsi dengan baik, tetapi jika ada yang memiliki pemikiran, saya akan berterima kasih telah berbagi.

Artikel ini ditulis untuk membantu mereka yang menemukan masalah seperti itu, karena saya tidak menemukan jawaban yang komprehensif di Internet, dan saya menghabiskan banyak waktu untuk mempelajari masalah dan menemukan solusinya.

Lihat juga:

  1. Menerapkan Indikator Kinerja SQL Server untuk Kueri, Prosedur Tersimpan, dan Pemicu
  2. Mengotomatiskan Defragmentasi Indeks di Database MS SQL Server


Alat yang berguna:

dbForge Query Builder untuk SQL Server – memungkinkan pengguna membuat kueri SQL yang kompleks dengan cepat dan mudah melalui antarmuka visual yang intuitif tanpa penulisan kode manual.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Menambahkan identitas ke kolom yang ada

  2. Meratakan rentang waktu yang berpotongan

  3. Buat Database di SQL Server 2017

  4. Panduan untuk CTE di SQL Server

  5. 3 Cara Mendapatkan Daftar Database di SQL Server (T-SQL)