Anda dapat memperkirakan apa yang Anda lihat di Monitor Kinerja dan Monitor Aktivitas untuk SQL Compilations/sec
dan Batch Requests/sec
, saat menjalankan beberapa kumpulan di jendela kueri terpisah sebagai tes, seperti yang dijelaskan di bawah ini.
Jendela Kueri 1:
DECLARE @t1 datetime;
DECLARE @t2 datetime;
DECLARE @CompVal1 int;
DECLARE @CompVal2 int;
DECLARE @ReCompVal1 int;
DECLARE @ReCompVal2 int;
DECLARE @BatchVal1 int;
DECLARE @BatchVal2 int;
DECLARE @ElapsedMS decimal(10,2);
SELECT @t1 = GETDATE()
, @CompVal1 = (
SELECT spi.cntr_value
FROM sys.sysperfinfo spi
WHERE spi.counter_name = 'SQL Compilations/sec '
)
, @ReCompVal1 = (
SELECT spi.cntr_value
FROM sys.sysperfinfo spi
WHERE spi.counter_name = 'SQL Re-Compilations/sec '
)
, @BatchVal1 = (
SELECT spi.cntr_value
FROM sys.sysperfinfo spi
WHERE spi.counter_name = 'Batch Requests/sec '
);
WAITFOR DELAY '00:00:10.000';
SELECT @t2 = GETDATE()
, @CompVal2 = (
SELECT spi.cntr_value
FROM sys.sysperfinfo spi
WHERE spi.counter_name = 'SQL Compilations/sec '
)
, @ReCompVal2 = (
SELECT spi.cntr_value
FROM sys.sysperfinfo spi
WHERE spi.counter_name = 'SQL Re-Compilations/sec '
)
, @BatchVal2 = (
SELECT spi.cntr_value
FROM sys.sysperfinfo spi
WHERE spi.counter_name = 'Batch Requests/sec '
);
SET @ElapsedMS = DATEDIFF(MILLISECOND, @t1, @t2);
SELECT ElapsedTimeMS = @ElapsedMS
, [SQL Compilations/sec] = (@CompVal2 - @CompVal1) / @ElapsedMS * 1000
, [SQL Recompilations/sec] = (@ReCompVal2 - @ReCompVal1) / @ElapsedMS * 1000
, [Batch Requests/sec] = (@BatchVal2 - @BatchVal1) / @ElapsedMS * 1000;
Di Jendela Kueri 2, jalankan yang berikut saat kode di atas sedang berjalan. Kode hanya menjalankan 100 batch T-SQL:
EXEC sys.sp_executesql N'SELECT TOP(1) o.name FROM sys.objects o;';
GO 100
Jika Anda kembali ke Jendela Kueri 1 Anda akan melihat sesuatu seperti ini:
╔═══════════════╦══════════════════════╦══════════ ══════════════╦════════════════════╗
║ ElapsedTimeMS ║ SQL Compilations / sec ║ SQL Recompilations / sec ║ Permintaan Batch / detik ║
╠═══════════════╬══════════════════════╬══════════ ══════════════╬════════════════════╣
║ 10020.00 ║ 10.07984031000 ║ 0.00000000000 ║ 10.07984031000 ║
╚═══════════════╩══════════════════════╩══════════ ══════════════╩════════════════════╝
Jika kita melihat kueri ini:
SELECT dest.text
, deqs.execution_count
FROM sys.dm_exec_query_stats deqs
CROSS APPLY sys.dm_exec_sql_text(deqs.plan_handle) dest
WHERE dest.text LIKE 'SELECT TOP(1)%'
Kami dapat mengonfirmasi ada 100 eksekusi permintaan tes.
Dalam hasil di atas, Anda dapat melihat kita semakin kompilasi setiap kali itu sp_executesql
mengeksekusi pernyataan. Rencana untuk itu tentunya sedang di-cache, namun kami melihat kompilasi untuk itu; apa yang memberi
The Microsoft Docs mengatakan ini tentang sp_executesql
:
sp_executesql memiliki perilaku yang sama dengan EXECUTE berkaitan dengan batch, lingkup nama, dan konteks database. Pernyataan Transact-SQL atau kumpulan dalam parameter sp_executesql @stmt tidak dikompilasi sampai pernyataan sp_executesql dieksekusi. Isi dari @stmt kemudian dikompilasi dan dieksekusi sebagai rencana eksekusi yang terpisah dari rencana eksekusi batch yang disebut sp_executesql.
Jadi, sp_executesql
itu sendiri sedang dikompilasi setiap kali dijalankan, bahkan jika rencana untuk teks perintah sudah ada dalam cache rencana. @ PaulWhite menunjukkan dalam jawabannya bahwa sebagian besar panggilan ke sp_executesql sebenarnya tidak di-cache.