คุณสามารถประมาณสิ่งที่คุณเห็นในการตรวจสอบประสิทธิภาพและการตรวจสอบกิจกรรมสำหรับ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;
ใน Query Window 2 ให้เรียกใช้สิ่งต่อไปนี้ขณะที่เรียกใช้รหัสข้างต้น รหัสนี้จะประมวลผลชุดที่ 100 ของ T-SQL:
EXEC sys.sp_executesql N'SELECT TOP(1) o.name FROM sys.objects o;';
GO 100
หากคุณเปลี่ยนกลับไปใช้ Query Window 1 คุณจะเห็นสิ่งนี้:
╔═══════════════╦══════════════════════╦══════════ ══════════════╦════════════════════╗
║ ElapsedTimeMS ║การคอมไพล์ด้วย SQL / วินาที║การคอมไพล์ของ SQL / วินาที Requ การร้องขอแบตช์ / วินาที║
╠═══════════════╬══════════════════════╬══════════ ══════════════╬════════════════════╣
║ 10020.00 ║ 10.07984031000 ║ 0.00000000000 ║ 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
เรียกใช้คำสั่ง แผนการสำหรับสิ่งนั้นถูกแคชไว้อย่างแน่นอน แต่เราก็เห็นการเรียบเรียง สิ่งที่ช่วยให้?
เอกสาร Microsoftพูดนี้เกี่ยวกับsp_executesql
:
sp_executesql มีพฤติกรรมเช่นเดียวกับ EXECUTE เกี่ยวกับแบตช์ขอบเขตของชื่อและบริบทฐานข้อมูล คำสั่ง Transact-SQL หรือแบตช์ในพารามิเตอร์ sp_executesql @stmt จะไม่ถูกคอมไพล์จนกว่าจะรันคำสั่ง sp_executesql เนื้อหาของ @stmt จะถูกรวบรวมและดำเนินการตามแผนการดำเนินการแยกต่างหากจากแผนการดำเนินการของแบทช์ที่เรียกว่า sp_executesql
ดังนั้นsp_executesql
ตัวเองจะถูกรวบรวมทุกครั้งที่มันทำงานแม้ว่าแผนสำหรับข้อความคำสั่งที่มีอยู่แล้วในแคชแผน @PaulWhite แสดงให้เห็นในคำตอบของเขาว่าส่วนใหญ่โทรไปยัง sp_executesql ไม่ได้เก็บไว้จริง