Pemindaian konstan membutuhkan 0 detik atau 2-3 menit

9

Kueri seperti di bawah ini yang dijamin tidak akan mengembalikan baris apa pun, membutuhkan waktu mulai 0 hingga 160 detik di salah satu server kami:

select col1, col2, col3
from tab1
where 0 = 1

Dua minggu lalu, ini terjadi enam kali dalam interval 48 jam. Minggu lalu permintaan yang sama memakan waktu ~ 0 detik. Saya memiliki log SQL aplikasi kita tetapi belum menemukan tersangka. Selain itu, saya pikir 0 / atas mana 0 = 1 jenis kueri tidak pernah mengenai halaman data, jadi harus tahan terhadap kunci data tingkat baris / halaman / tabel? Skema ini tidak tersentuh oleh SQL (dikenal) apa pun.

Karena masalahnya tidak konsisten, dan server berada di bawah beban yang sangat berat, saya ingin memahami teori di balik apa yang terjadi sebelum melampirkan profiler SQL. Kueri lain berjalan tanpa masalah selama penundaan ini. Masalah yang diketahui dalam aplikasi ini adalah tingginya jumlah kueri SQL yang dibuat secara dinamis - sekitar 200k kueri unik dari total 850k (log) kueri selama 48 jam, dapatkah ini menyebabkan masalah seperti ini?

Server menjalankan SQL Server 2005 edisi standar, RAM 96 GB, disk pada SAN dan 4 CPU / 16 core. File dan filegroup basis data dioptimalkan dengan baik dan seharusnya tidak menjadi masalah (tapi kami melihat ini secara terpisah).

Setiap petunjuk di mana mencarinya sangat dihargai.

Sunting: Sempurna! Memutar ulang kueri untuk menambahkan rencana eksekusi, dan butuh 1 menit 35 detik. Berikut rencana eksekusi dan tangkapan layar yang menunjukkan durasi kueri: Rencana kueri

Sunting 2: detail waktu statistik untuk putaran kedua. Tampaknya lambat secara konsisten saat ini, jadi kami akan melampirkan profiler dan perfmon:

SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 97402 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.
EventHorizon
sumber
Bisakah Anda memasukkan rencana eksekusi? CTRL + M di jendela permintaan sebelum eksekusi.
Craig Efrein
2
Mungkinkah itu masalah penguncian? Pernyataan DML dari sesi lain yang memblokir pilih di atas meja (yang merupakan perilaku default di SQL Server 2005)
a_horse_with_no_name
Tidak ada pernyataan DML yang tidak diketahui, yang merupakan satu-satunya penyebab yang dapat saya pikirkan, tetapi kami masih menyelidiki ini. Rencana eksekusi ditambahkan ke pertanyaan.
EventHorizon
Dari apa yang saya baca, ini hanya salah satu dari rencana eksekusi sepele yang MSSQL gunakan untuk menghindari pembacaan tumpukan dan indeks ketika pengoptimal tahu tidak ada baris yang akan dikembalikan
Craig Efrein
1
Melihat kasus yang terlihat seperti ini. Ternyata itu memicu statistik pembaruan (statistik pembaruan otomatis diaktifkan dan rencana pemeliharaan rusak).
Joshua

Jawaban:

18

Tampaknya seolah-olah dengan ... WHERE 0 = 1klausa bahwa masih akan ada persyaratan untuk maksud shared ( IS) kunci di atas meja. Mari kita buktikan ini:

Saya akan memulai dengan membuat tabel tes:

use TestDb1;
go

create table dbo.MyTestTable1
(
    Id int identity(1, 1) not null,
    SomeInt int not null
);
go

insert into dbo.MyTestTable1 (SomeInt)
values (10), (20), (30), (40), (50);
go

Sekarang saya memiliki tabel pengujian saya, dalam satu sesi (jendela permintaan) saya akan menjalankan yang berikut ini untuk menempatkan Xkunci ( ) eksklusif pada dbo.MyTestTable1:

use TestDb1;
go

begin tran;
    select
        Id, SomeInt
    from dbo.MyTestTable1 with (tablockx);
--commit tran;

Saya dapat memverifikasi kunci eksklusif dengan melihat sys.dm_tran_locksDMV. Kemudian di sesi lain (jendela permintaan baru) saya melakukan persis apa yang dilakukan permintaan Anda:

use TestDb1;
go

select
    Id, SomeInt
from dbo.MyTestTable1
where 0 = 1;

Pada pandangan pertama saya melihat bahwa itu tidak selesai. Melihat sys.dm_exec_requests, saya tahu persis mengapa ini terjadi:

select
    r.session_id,
    r.status,
    r.wait_type,
    r.wait_time,
    r.wait_resource,
    r.blocking_session_id
from sys.dm_exec_requests r
cross apply sys.dm_exec_sql_text(r.sql_handle) st
where st.text like '%where 0 = 1%'
and r.session_id <> @@spid;

masukkan deskripsi gambar di sini

Saya dapat melihat di sini bahwa ... WHERE 0 = 1permintaan saya sedang menunggu ISkunci untuk objek ini (yang diterjemahkan oleh object_id dbo.MyTestTable1).

Saya sama sekali tidak mengatakan bahwa konkurensi adalah masalah Anda , tetapi dari suaranya Anda menunjukkan gejalanya. Contoh di atas adalah untuk membuktikan bahwa Anda tidak dibebaskan dari mengunci dan memblokir bahkan dengan WHEREklausa yang tidak akan pernah mengembalikan data.

Yang bisa kita lakukan hanyalah menebak, jadi apa yang perlu Anda lakukan ketika "butuh waktu lama" adalah untuk melihat apa yang dilakukan permintaan itu yang butuh waktu lama. Jika menunggu sesuatu, maka lihat apa yang menunggu.

Thomas Stringer
sumber
1

Bergantung pada seberapa spiky dan thread permintaan kueri Anda, sistem Anda mungkin hanya mengantri permintaan itu. Jumlah pekerja default (yaitu jumlah utas server SQL simultan) untuk pengaturan Anda harus sekitar 700.

Lihat sys.dm_os_schedulers dan sys.dm_os_waiting_tasks untuk melihat apakah itu bisa menjadi masalah.

Sascha Rambeaud
sumber
Saran yang bagus, tetapi masalah akhirnya menjadi kunci konyol.
EventHorizon
Saya tidak benar-benar yakin, karena 700 pekerja banyak, tetapi mudah untuk memeriksa (dan dengan demikian mengecualikan)
Sascha Rambeaud