สาเหตุที่size_in_bytes
เขตข้อมูลของsys.dm_exec_cached_plans
DMV อย่างน้อยก็ในแง่ของ "แผนการรวบรวม" มีขนาดใหญ่กว่าCachedPlanSize
แอตทริบิวต์ของQueryPlan
โหนดในแผน XML เนื่องจากแผนการรวบรวมไม่เหมือนกับแผนแบบสอบถาม แผนคอมไพล์ประกอบด้วยหน่วยความจำหลายออบเจ็กต์ขนาดรวมซึ่งเท่ากับsize_in_bytes
ฟิลด์ ดังนั้นคำอธิบายของ " จำนวนไบต์ที่ใช้โดยวัตถุแคช " ที่คุณพบในเอกสารมีความถูกต้อง เป็นเพียงการตีความผิดที่ "วัตถุแคช" หมายถึงชื่อ DMV ได้ง่ายและคำว่า "แผน" มีความหมายหลายอย่าง
Compiled Plan เป็นคอนเทนเนอร์ที่เก็บข้อมูลหลากหลายที่เกี่ยวข้องกับแบทช์แบบสอบถาม(เช่นไม่ใช่คำสั่งเดียว) หนึ่ง (หรือมากกว่า) ของชิ้นส่วนเหล่านั้นเป็นแผนเคียวรี แผนการที่คอมไพล์มีหน่วยความจำระดับสูงสุดวัตถุวัตถุของMEMOBJ_COMPILE_ADHOCซึ่งเป็นแถวในsys.dm_os_memory_objects
ที่ถูกเชื่อมโยงผ่านmemory_object_address
เขตข้อมูลใน DMV ทั้งสอง หน่วยความจำวัตถุนี้มีตารางสัญลักษณ์การรวบรวมพารามิเตอร์เชื่อมโยงไปยังวัตถุที่เกี่ยวข้องแคช accessor แคชเมตาดาต้า TDS และอาจเป็นไปได้บางรายการอื่น ๆ แผนการคอมไพล์ถูกแชร์ระหว่างเซสชัน / ผู้ใช้ที่ดำเนินการแบทช์เดียวกันด้วยการตั้งค่าเซสชันเดียวกัน อย่างไรก็ตามวัตถุที่เกี่ยวข้องบางอย่างไม่ถูกแชร์ระหว่างเซสชัน / ผู้ใช้
แผนการคอมไพล์ยังมีวัตถุที่ต้องพึ่งพาอย่างน้อยหนึ่งรายการที่สามารถพบได้โดยการส่งผ่านplan_handle
( sys.dm_exec_cached_plans
เข้า) เข้าสู่sys.dm_exec_cached_plan_dependent_objects
DMF มีวัตถุที่ต้องพึ่งพาสองชนิด: แผนปฏิบัติการ (หน่วยความจำวัตถุ = MEMOBJ_EXECUTE ) และเคอร์เซอร์ (วัตถุหน่วยความจำ = MEMOBJ_CURSOREXEC ) จะมีวัตถุเคอร์เซอร์ 0 ตัวหรือมากกว่าหนึ่งตัวต่อเคอร์เซอร์ จะมีวัตถุแผนปฏิบัติการหนึ่งรายการขึ้นไปหนึ่งวัตถุสำหรับแต่ละผู้ใช้ที่ดำเนินการแบทช์เดียวกันดังนั้นแผนปฏิบัติการไม่ได้แบ่งปันระหว่างผู้ใช้ แผนปฏิบัติการมีพารามิเตอร์รันไทม์และข้อมูลตัวแปรโลคัลสถานะรันไทม์เช่นคำสั่งที่ดำเนินการในปัจจุบันรหัสวัตถุสำหรับวัตถุที่สร้างขึ้นในเวลาทำงาน (ฉันถือว่านี่หมายถึงตัวแปรตารางตารางชั่วคราวขั้นตอนการจัดเก็บชั่วคราว ฯลฯ ) และรายการอื่น ๆ ที่เป็นไปได้
แต่ละคำสั่งภายในชุดคำสั่งหลายชุดจะมีอยู่ในคำชี้แจงที่รวบรวม (หน่วยความจำวัตถุ = MEMOBJ_STATEMENT ) ขนาดของแต่ละคำสั่งที่คอมไพล์ (เช่นpages_in_bytes
) หารด้วย 1024 ควรตรงกับCachedPlanSize="xx"
ค่าของ<QueryPlan>
โหนดในแผน XML คำสั่งที่คอมไพล์มักจะมีหนึ่ง (อาจมากกว่า?) เชื่อมโยงแบบสอบถามแบบสอบถามรันไทม์ (หน่วยความจำวัตถุ = MEMOBJ_XSTMT ) สุดท้ายสำหรับแต่ละแผนแบบสอบถามรันไทม์ที่เป็นแบบสอบถามควรมีบริบทการดำเนินการแบบสอบถามที่เกี่ยวข้อง (หน่วยความจำวัตถุ = MEMOBJ_QUERYEXECCNTXTFORSE )
สำหรับคำสั่งที่คอมไพล์แบทช์คำสั่งเดี่ยวไม่มีคำสั่งที่คอมไพล์แยกต่างหาก (เช่นMEMOBJ_STATEMENT ) หรือแผนคิวรีรันไทม์แยกต่างหาก (เช่นMEMOBJ_XSTMT ) ค่าสำหรับแต่ละวัตถุเหล่านั้นจะถูกเก็บไว้ในวัตถุแผนหลักที่รวบรวม (เช่นMEMOBJ_COMPILE_ADHOC ) และในกรณีนั้นpages_in_bytes
ค่าสำหรับวัตถุหลักนั้นหารด้วย 1024 ควรตรงกับCachedPlanSize
ขนาดใน<QueryPlan>
โหนดของแผน XML ค่าเหล่านั้นจะไม่ถือเอาเป็นอย่างไรก็ตามในแบทช์หลายคำสั่ง
size_in_bytes
คุ้มค่าที่จะได้รับจากข้อสรุปรายการในsys.dm_os_memory_objects
DMV (รายการที่ระบุไว้ข้างต้นเป็นตัวหนา) ทั้งหมดที่เกี่ยวข้องกับdm_os_memory_objects.page_allocator_address
การที่แผนรวบรวม เคล็ดลับในการรับค่าที่ถูกต้องคือการขอรับmemory_object_address
จากsys.dm_exec_cached_plans
สำหรับแผนคอมไพล์เฉพาะก่อนจากนั้นใช้เพื่อรับแถวMEMOBJ_COMPILE_ADHOC ที่สอดคล้องกันจากsys.dm_os_memory_objects
ตามmemory_object_address
ฟิลด์ จากนั้นจับpage_allocator_address
ค่าจากsys.dm_os_memory_objects
แถวนั้นและใช้เพื่อจับแถวทั้งหมดจากsys.dm_os_memory_objects
ที่มีpage_allocator_address
ค่าเท่ากัน (โปรดทราบว่าเทคนิคนี้ใช้ไม่ได้กับวัตถุประเภทแคชอื่น: Parse Tree , Extended Proc , CLR Compiled ProcและCLR Compiled Func.)
ใช้memory_object_address
ค่าที่ได้รับจากsys.dm_exec_cached_plans
คุณสามารถดูส่วนประกอบทั้งหมดของแผนรวบรวมผ่านแบบสอบถามต่อไปนี้:
DECLARE @CompiledPlanAddress VARBINARY(8) = 0x00000001DC4A4060;
SELECT obj.memory_object_address, obj.pages_in_bytes, obj.type
FROM sys.dm_os_memory_objects obj
WHERE obj.page_allocator_address = (
SELECT planobj.page_allocator_address
FROM sys.dm_os_memory_objects planobj
WHERE planobj.memory_object_address = @CompiledPlanAddress
)
ORDER BY obj.[type], obj.pages_in_bytes;
แบบสอบถามด้านล่างนี้แสดงรายการแผนรวบรวมทั้งหมดsys.dm_exec_cached_plans
พร้อมกับแผนแบบสอบถามและคำสั่งสำหรับแต่ละชุด แบบสอบถามโดยตรงด้านบนจะรวมอยู่ในแบบสอบถามด้านล่างผ่าน XML เป็นMemoryObjects
ฟิลด์:
SELECT cplan.bucketid,
cplan.pool_id,
cplan.refcounts,
cplan.usecounts,
cplan.size_in_bytes,
cplan.memory_object_address,
cplan.cacheobjtype,
cplan.objtype,
cplan.plan_handle,
'---' AS [---],
qrypln.[query_plan],
sqltxt.[text],
'---' AS [---],
planobj.pages_in_bytes,
planobj.pages_in_bytes / 1024 AS [BaseSingleStatementPlanKB],
'===' AS [===],
cplan.size_in_bytes AS [TotalPlanBytes],
bytes.AllocatedBytes,
(SELECT CONVERT(VARCHAR(30), obj.memory_object_address, 1)
AS [memory_object_address], obj.pages_in_bytes, obj.[type]
--,obj.page_size_in_bytes
FROM sys.dm_os_memory_objects obj
WHERE obj.page_allocator_address = planobj.page_allocator_address
FOR XML RAW(N'object'), ROOT(N'memory_objects'), TYPE) AS [MemoryObjects]
FROM sys.dm_exec_cached_plans cplan
OUTER APPLY sys.dm_exec_sql_text(cplan.[plan_handle]) sqltxt
OUTER APPLY sys.dm_exec_query_plan(cplan.[plan_handle]) qrypln
INNER JOIN sys.dm_os_memory_objects planobj
ON planobj.memory_object_address = cplan.memory_object_address
OUTER APPLY (SELECT SUM(domo.[pages_in_bytes]) AS [AllocatedBytes]
FROM sys.dm_os_memory_objects domo
WHERE domo.page_allocator_address = planobj.page_allocator_address) bytes
WHERE cplan.parent_plan_handle IS NULL
AND cplan.cacheobjtype IN (N'Compiled Plan', N'Compiled Plan Stub')
--AND cplan.plan_handle = 0x06000D0031CD572910529CE001000000xxxxxxxx
ORDER BY cplan.objtype, cplan.plan_handle;
โปรดทราบว่า:
TotalPlanBytes
ฟิลด์เป็นเพียงอีกคำสั่งของsys.dm_exec_cached_plans.size_in_bytes
สนาม
AllocatedBytes
ฟิลด์คือผลรวมของวัตถุหน่วยความจำที่เกี่ยวข้องที่มักจะตรงกับTotalPlanBytes
(คือsize_in_bytes
)
AllocatedBytes
ฟิลด์เป็นครั้งคราวจะสูงกว่าTotalPlanBytes
(คือsize_in_bytes
) เนื่องจากการใช้หน่วยความจำที่เพิ่มขึ้นระหว่างการดำเนินการ สิ่งนี้ดูเหมือนจะเกิดขึ้นส่วนใหญ่เนื่องจากการคอมไพล์ซ้ำ (ซึ่งควรเห็นได้ชัดกับการusecounts
แสดงฟิลด์1
)
BaseSingleStatementPlanKB
ฟิลด์ควรตรงกับCachedPlanSize
แอตทริบิวต์ของQueryPlan
โหนดใน XML แต่เฉพาะเมื่อใช้ชุดคำเดียว
- สำหรับชุดงานที่มีหลายแบบสอบถามควรมีการทำเครื่องหมายเป็นแถว
MEMOBJ_STATEMENT
ในsys.dm_os_memory_objects
หนึ่งแบบสอบถามสำหรับแต่ละแบบสอบถาม pages_in_bytes
สนามแถวเหล่านี้ควรจะตรงกับแต่ละ<QueryPlan>
โหนดของแผนการของ XML
แหล่งข้อมูล: