आप अनुमान लगा सकता है क्या आप के लिए प्रदर्शन मॉनिटर और गतिविधि मॉनिटर में देखते हैं SQL Compilations/sec
और Batch Requests/sec
, एक परीक्षण के रूप में अलग क्वेरी विंडो में कुछ बैचों चलाते समय विवरण नीचे दिया गया।
क्वेरी विंडो 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;
क्वेरी विंडो 2 में, उपरोक्त कोड के चलने के दौरान निम्नलिखित को चलाएँ। कोड केवल 100 T-SQL बैच निष्पादित करता है:
EXEC sys.sp_executesql N'SELECT TOP(1) o.name FROM sys.objects o;';
GO 100
यदि आप क्वेरी विंडो 1 पर वापस जाते हैं तो आपको कुछ इस तरह दिखाई देगा:
╔═══════════════╦══════════════════════╦══════════ ══════════════╦════════════════════╗
Ations ElapsedTimeMS Comp एसक्यूएल संकलनों / सेकंड omp एसक्यूएल Recompilations / सेकंड atch बैच अनुरोध और सेकंड Time
╠═══════════════╬══════════════════════╬══════════ ══════════════╬════════════════════╣
║ 10020.00 79 10.07984031000 00000 0.00000000000 79 10.07984031000 ║
╚═══════════════╩══════════════════════╩══════════ ══════════════╩════════════════════╝
यदि हम इस प्रश्न को देखते हैं:
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)%'
हम पुष्टि कर सकते हैं कि परीक्षण क्वेरी के 100 निष्पादन थे।
उपरोक्त परिणामों में, आप देख सकते हैं कि जब भी sp_executesql
कथन निष्पादित होता है , तब हम संकलन कर रहे हैं । उस योजना को निश्चित रूप से कैश किया जा रहा है, फिर भी हम इसके लिए एक संकलन देखते हैं; क्या देता है?
माइक्रोसॉफ्ट डॉक्स के बारे में यह कहना sp_executesql
:
sp_executesql में बैचों, नामों के दायरे और डेटाबेस के संदर्भ में EXECUTE जैसा ही व्यवहार होता है। Sp_executesql @stmt पैरामीटर में Transact-SQL स्टेटमेंट या बैच तब तक संकलित नहीं किया जाता है जब तक कि sp_executesql स्टेटमेंट निष्पादित न हो जाए। @Stmt की सामग्री तब संकलित की गई निष्पादन योजना के रूप में संकलित और निष्पादित की जाती है, जिसे sp_executesql कहा जाता है।
इसलिए, प्रत्येक बार चलने वाले समय में sp_executesql
खुद को संकलित किया जा रहा है, भले ही कमांड पाठ की योजना पहले से ही योजना कैश में हो। @PaWWite अपने जवाब में दिखाती है कि sp_executesql के अधिकांश कॉल वास्तव में कैश नहीं होते हैं।