Apakah pemicu kompilasi setiap kali?

22

Kami memecahkan masalah server yang memiliki utilisasi CPU tinggi. Setelah menemukan bahwa pertanyaan tidak benar-benar menyebabkannya, kami mulai mencari kompilasi.

Monitor Kinerja menunjukkan kurang dari 50 Kompilasi / detik dan kurang dari 15 Kompilasi / detik.

Setelah menjalankan sesi XE mencari kompilasi, kami melihat ribuan kompilasi per detik.

Sistem ini menggunakan pemicu untuk mengaudit perubahan. Sebagian besar kompilasi disebabkan oleh pemicu. Pemicu sys.dm_tran_active_transactions referensi.

Pikiran pertama kami adalah bahwa mungkin merujuk DMV di pemicu akan membuatnya mengkompilasi setiap kali, atau mungkin hanya DMV spesifik ini yang akan menyebabkannya. Jadi saya mulai menguji teori itu. Itu mengkompilasi setiap kali, tapi saya belum memeriksa apakah pemicu mengkompilasi setiap kali dipicu ketika itu tidak mereferensikan DMV dan bukan hardcodes nilai. Itu masih mengkompilasi setiap kali dipicu. Menjatuhkan pelatuk menghentikan kompilasi.

  1. Kami menggunakan sqlserver.query_pre_execution_showplan dalam sesi XE untuk melacak kompilasi. Mengapa ada perbedaan antara itu dan penghitung PerfMon?
  2. Apakah normal bahwa Anda mendapatkan acara kompilasi setiap kali pemicu berjalan?

Skrip repro:

CREATE TABLE t1 (transaction_id int, Column2 varchar(100));
CREATE TABLE t2 (Column1 varchar(max), Column2 varchar(100));
GO

CREATE TRIGGER t2_ins
ON t2
AFTER INSERT
AS

INSERT INTO t1
SELECT (SELECT TOP 1 transaction_id FROM sys.dm_tran_active_transactions), Column2
FROM inserted;
GO

--Both of these show compilation events
INSERT INTO t2 VALUES ('row1', 'value1');
INSERT INTO t2 VALUES ('row2', 'value2');
GO

ALTER TRIGGER t2_ins
ON t2
AFTER INSERT
AS

INSERT INTO t1
SELECT 1000, Column2
FROM inserted;
GO

--Both of these show compilation events
INSERT INTO t2 VALUES ('row3', 'value3');
INSERT INTO t2 VALUES ('row4', 'value4');

DROP TRIGGER t2_ins;

--These do not show compilation events
INSERT INTO t2 VALUES ('row5', 'value5');
INSERT INTO t2 VALUES ('row6', 'value6');

DROP TABLE t1, t2;
Tara Kizer
sumber

Jawaban:

20

Acara XE yang digunakan mengarahkan Anda secara tidak benar untuk berpikir bahwa pemicu sebenarnya mengkompilasi setiap eksekusi. Ada dua peristiwa diperpanjang query_pre_execution_showplan dan query_post_compilation_showplan yang memiliki deskripsi serupa, tetapi berbeda dengan satu kata penting:

query_pre_execution_showplan

Terjadi setelah pernyataan SQL dikompilasi. Acara ini mengembalikan representasi XML dari perkiraan rencana kueri yang dihasilkan saat kueri dioptimalkan . Menggunakan acara ini dapat memiliki overhead kinerja yang signifikan sehingga hanya digunakan ketika memecahkan masalah atau memantau masalah tertentu untuk periode waktu yang singkat.

query_post_compilation_showplan

Terjadi setelah pernyataan SQL dikompilasi. Acara ini mengembalikan representasi XML dari perkiraan rencana kueri yang dihasilkan saat kueri dikompilasi . Menggunakan acara ini dapat memiliki overhead kinerja yang signifikan sehingga hanya digunakan ketika memecahkan masalah atau memantau masalah tertentu untuk periode waktu yang singkat.

Peristiwa tidak persis sama dalam uraian dan terjadi pada waktu yang berbeda dari pengujian lebih lanjut menggunakan repro Anda. Menggunakan definisi sesi acara yang jauh lebih besar, mudah untuk melihat di mana kompilasi sebenarnya terjadi.

masukkan deskripsi gambar di sini

Di sini Anda dapat melihat kompilasi pertama yang terjadi untuk pernyataan penyisipan sebagai rencana yang disiapkan yang diparameterisasi otomatis di kotak hijau. Pemicu dikompilasi di kotak merah dan rencana dimasukkan ke dalam cache seperti yang ditunjukkan oleh acara sp_cache_insert. Kemudian di kotak oranye eksekusi pemicu mendapat hit cache dan menggunakan kembali rencana pemicu untuk pernyataan INSERT kedua dalam batch, jadi itu tidak mengkompilasi setiap eksekusi perintah INSERT dan rencana itu bisa digunakan kembali seperti yang Anda lihat dengan acara sp_cache_hit untuk pemicunya.

Jika kami menjalankan kedua pernyataan INSERT secara individual lagi setelah eksekusi pertama, pemicu tidak dapat dikompilasi lagi seperti yang ditunjukkan dalam peristiwa di bawah ini:

masukkan deskripsi gambar di sini

Di sini pernyataan pertama menemukan hit cache untuk versi pernyataan yang disiapkan parameter-otomatis yang disiapkan dalam cache tetapi ketinggalan untuk batch adhoc yang dikirimkan. Pemicu mendapat hit cache dan tidak dikompilasi lagi seperti yang ditunjukkan pada blok merah acara. Blok peristiwa yang hijau mengulangi perilaku ini untuk pernyataan INSERT kedua yang dijalankan sebagai kumpulan terpisah. Namun, dalam setiap kasus, Anda masih melihat peristiwa queri_pre_execution_showplan yang saya hanya bisa atribut perbedaan dioptimalkan vs dikompilasi dalam deskripsi acara, tetapi pemicu tidak mengkompilasi untuk setiap eksekusi seperti yang ditunjukkan oleh serangkaian acara ini.

Jonathan Kehayias
sumber
Jika Anda melihat tangkapan layar pertama, acara sql_batch_statistics yang tidak di-cache ada di koleksi tetapi hanya diaktifkan untuk eksekusi pertama dari kumpulan sql ketika cache dihapus dan rencana auto-parameterized untuk INSERT tidak ada dalam cache rencana. Setelah itu acara uncached_sql_batch_statistics tidak menyala lagi.
Jonathan Kehayias
Query_post_compilation_showplan menunjukkan hanya beberapa kompilasi pada pemicu tetapi tidak jumlah besar yang kami lihat di acara lain. Kami memang menemukan beberapa nugget yang menarik dengan query_post_compilation_showplan. Terima kasih atas informasinya, Jonathan!
Tara Kizer
13

Tidak. Pemicu tidak selalu dikompilasi ulang. Namun, pernyataan kueri yang sederhana, tidak membuat rencana mereka di-cache dan karenanya akan selalu dikompilasi ulang.

Pemicu dikompilasi ulang jika jumlah baris yang dimasukkan atau dihapus berubah secara signifikan. Lihat: https://technet.microsoft.com/en-us/library/ms181055.aspx

Saya tidak tahu apakah mereka memiliki hal yang sama di XEvents, tetapi dalam SQL Trace, kompilasi ulang memiliki subkelas acara yang memberi tahu Anda mengapa itu dikompilasi ulang. Itu dijelaskan di tautan yang sama di atas.

Robert L Davis
sumber
1
Kami melihat kompilasi daripada kompilasi. Kita akan melihat server besok dan memeriksa apakah itu karena pernyataan kueri yang sederhana atau apakah itu karena jumlah baris. Terima kasih!
Tara Kizer