ในขณะที่ฉันเช่น @Thomas เห็นด้วยอย่างสมบูรณ์กับ @Aaron ในความคิดเห็นเกี่ยวกับคำถามเกี่ยวกับ "การใช้งาน CPU ต่อฐานข้อมูล" อย่างถูกต้องหรือมีประโยชน์ฉันอย่างน้อยสามารถตอบคำถามว่าทำไมทั้งสองข้อจึงเป็นเช่นนั้น ต่าง และสาเหตุที่ทำให้พวกเขาแตกต่างกันจะระบุว่าอันใดที่ถูกต้องมากกว่าถึงแม้ว่าความแม่นยำระดับสูงจะยังคงสัมพันธ์กับสิ่งที่ไม่ถูกต้องโดยเฉพาะดังนั้นจึงยังไม่แม่นยำ ;-)
แบบสอบถามแรกใช้sys.dm_exec_query_statsเพื่อรับข้อมูล CPU (เช่นtotal_worker_time
) หากคุณไปที่หน้าที่เชื่อมโยงซึ่งเป็นเอกสาร MSDN สำหรับ DMV นั้นคุณจะเห็นคำนำประโยคสั้น ๆ 3 ประโยคและประโยคที่ 2 ของประโยคเหล่านี้ให้สิ่งที่เราต้องเข้าใจบริบทของข้อมูลนี้ ("ความน่าเชื่อถือ") และ "มันเปรียบเทียบกับsys.sysprocesses
" อย่างไร ประโยคทั้งสองนั้นคือ:
ส่งคืนสถิติประสิทธิภาพโดยรวมสำหรับแผนการสืบค้นที่แคชใน SQL Server ... เมื่อแผนถูกลบออกจากแคชแถวที่เกี่ยวข้องจะถูกลบออกจากมุมมองนี้
ประโยคแรก "ส่งคืนสถิติประสิทธิภาพโดยรวม " บอกเราว่าข้อมูลใน DMV นี้ (เหมือนกับคนอื่น ๆ หลายคน) นั้นเป็นข้อมูลสะสมและไม่เฉพาะเจาะจงกับแบบสอบถามที่กำลังทำงานอยู่เท่านั้น นอกจากนี้ยังระบุด้วยเขตข้อมูลใน DMV นั้นที่ไม่ได้เป็นส่วนหนึ่งของแบบสอบถามในคำถามexecution_count
ซึ่งแสดงให้เห็นอีกครั้งว่านี่เป็นข้อมูลสะสม และมันก็เป็นประโยชน์มากที่จะมีข้อมูลเหล่านี้จะสะสมในขณะที่คุณจะได้รับค่าเฉลี่ย ฯลฯ execution_count
โดยการหารบางส่วนของตัวชี้วัดโดย
ประโยคที่สอง "แผนที่ถูกลบออกจากแคชก็ถูกลบออกจาก DMV นี้ด้วย" แสดงว่ามันไม่ได้เป็นภาพที่สมบูรณ์เลยโดยเฉพาะอย่างยิ่งถ้าเซิร์ฟเวอร์มีแคชแผนที่ค่อนข้างสมบูรณ์อยู่แล้วและอยู่ภายใต้ภาระและด้วยเหตุนี้แผนการหมดอายุ ค่อนข้างบ่อย นอกจากนี้ DMV ส่วนใหญ่จะถูกรีเซ็ตเมื่อเซิร์ฟเวอร์รีเซ็ตดังนั้นจึงไม่ใช่ประวัติจริงแม้ว่าแถวเหล่านี้จะไม่ถูกลบออกเมื่อแผนหมดอายุ
sys.sysprocesses
ตอนนี้ให้ความคมชัดของข้างต้นด้วย มุมมองระบบนี้แสดงเฉพาะสิ่งที่กำลังทำงานอยู่เช่นเดียวกับการรวมกันของsys.dm_exec_connections , sys.dm_exec_sessionsและsys.dm_exec_requests (ซึ่งระบุไว้ในหน้าเชื่อมโยงสำหรับsys.dm_exec_sessions
) นี่เป็นมุมมองที่แตกต่างอย่างสิ้นเชิงของเซิร์ฟเวอร์เมื่อเปรียบเทียบกับsys.dm_exec_query_stats
DMV ซึ่งเก็บข้อมูลแม้หลังจากกระบวนการเสร็จสิ้น ความหมายเกี่ยวข้องกับ "ผลลัพธ์จากแบบสอบถามที่สองผิดหรือไม่" คำถามพวกเขาไม่ผิดพวกเขาเกี่ยวข้องกับแง่มุมที่แตกต่างกัน (เช่นกรอบเวลา) ของสถิติประสิทธิภาพ
ดังนั้นการใช้แบบสอบถามsys.sysprocesses
จึงดูที่ "ตอนนี้" เท่านั้น และการสืบค้นที่ใช้sys.dm_exec_query_stats
นั้นส่วนใหญ่ (อาจ) สิ่งที่เกิดขึ้นตั้งแต่การรีสตาร์ทครั้งล่าสุดของบริการ SQL Server (หรือการรีบูตระบบ) สำหรับการวิเคราะห์ประสิทธิภาพโดยทั่วไปดูเหมือนว่าsys.dm_exec_query_stats
จะดีกว่ามาก แต่ก็มีข้อมูลที่มีประโยชน์อยู่ตลอดเวลา และในทั้งสองกรณีคุณต้องพิจารณาจุดที่ @Aaron ทำไว้ในความคิดเห็นของคำถาม (ตั้งแต่ลบออก) เกี่ยวกับความถูกต้องของค่า "database_id" ในตอนแรก (เช่นจะแสดงเฉพาะฐานข้อมูลที่แอ็คทีฟที่เริ่มต้นโค้ด ไม่จำเป็นว่าจะเกิด "ปัญหา" ที่ใด)
แต่ถ้าคุณเพียงแค่ต้อง / ต้องการที่จะรับความรู้สึกของสิ่งที่เกิดขึ้นในขณะนี้ทั่วทั้งฐานข้อมูลทั้งหมดอาจจะเป็นเพราะสิ่งที่จะชะลอตัวลงในขณะนี้คุณจะดีกว่าใช้การรวมกันของsys.dm_exec_connections
, sys.dm_exec_sessions
และsys.dm_exec_requests
(และไม่ได้เลิกใช้sys.sysprocesses
) เพียงจำไว้ว่าคุณกำลังค้นหา / เพื่อค้นหาไม่ใช่ฐานข้อมูลเนื่องจากแบบสอบถามสามารถเข้าร่วมในหลายฐานข้อมูลรวมถึง UDF จากฐานข้อมูลหนึ่งฐานหรือมากกว่าเป็นต้น
แก้ไข:
หากข้อกังวลโดยรวมลดผู้ใช้ CPU สูงให้ค้นหาคำสั่งที่ใช้ CPU มากที่สุดเนื่องจากฐานข้อมูลไม่ได้ใช้ CPU จริง (การดูฐานข้อมูลอาจใช้งานได้กับ บริษัท โฮสติ้งที่แยกแต่ละฐานข้อมูลและ เป็นของลูกค้ารายอื่น)
ข้อความค้นหาต่อไปนี้จะช่วยระบุข้อความค้นหาที่มีการใช้งาน CPU โดยเฉลี่ยสูง มันรวมข้อมูลใน query_stats DMV เนื่องจากระเบียนเหล่านั้นสามารถแสดงแบบสอบถามเดียวกัน (ใช่ชุดย่อยเดียวกันของชุดแบบสอบถาม) หลายครั้งแต่ละครั้งมีแผนปฏิบัติการที่แตกต่างกัน
;WITH cte AS
(
SELECT stat.[sql_handle],
stat.statement_start_offset,
stat.statement_end_offset,
COUNT(*) AS [NumExecutionPlans],
SUM(stat.execution_count) AS [TotalExecutions],
((SUM(stat.total_logical_reads) * 1.0) / SUM(stat.execution_count)) AS [AvgLogicalReads],
((SUM(stat.total_worker_time) * 1.0) / SUM(stat.execution_count)) AS [AvgCPU]
FROM sys.dm_exec_query_stats stat
GROUP BY stat.[sql_handle], stat.statement_start_offset, stat.statement_end_offset
)
SELECT CONVERT(DECIMAL(15, 5), cte.AvgCPU) AS [AvgCPU],
CONVERT(DECIMAL(15, 5), cte.AvgLogicalReads) AS [AvgLogicalReads],
cte.NumExecutionPlans,
cte.TotalExecutions,
DB_NAME(txt.[dbid]) AS [DatabaseName],
OBJECT_NAME(txt.objectid, txt.[dbid]) AS [ObjectName],
SUBSTRING(txt.[text], (cte.statement_start_offset / 2) + 1,
(
(CASE cte.statement_end_offset
WHEN -1 THEN DATALENGTH(txt.[text])
ELSE cte.statement_end_offset
END - cte.statement_start_offset) / 2
) + 1
)
FROM cte
CROSS APPLY sys.dm_exec_sql_text(cte.[sql_handle]) txt
ORDER BY cte.AvgCPU DESC;
AvgCPU
มิลลิวินาทีหรือไม่