Lý do mà size_in_bytes
trường sys.dm_exec_cached_plans
DMV, ít nhất là về "Gói biên dịch", lớn hơn CachedPlanSize
thuộc tính của QueryPlan
nút trong kế hoạch XML là vì Kế hoạch biên dịch không giống với Kế hoạch truy vấn. Gói tổng hợp bao gồm nhiều đối tượng bộ nhớ, kích thước kết hợp tương đương với size_in_bytes
trường. Vì vậy, mô tả về " Số byte được tiêu thụ bởi đối tượng bộ đệm " mà bạn tìm thấy trong tài liệu là chính xác; chỉ đơn giản là dễ hiểu sai ý nghĩa của "đối tượng bộ đệm" được đặt tên của DMV và thuật ngữ "kế hoạch" có nhiều nghĩa.
Gói biên dịch là một thùng chứa các phần thông tin khác nhau liên quan đến lô truy vấn (nghĩa là không chỉ một câu lệnh), một (hoặc nhiều) trong số các phần đó là (các) gói truy vấn. Các gói được biên dịch có Đối tượng bộ nhớ cấp cao nhất là MEMOBJ_COMPILE_ADHOC , là hàng trong sys.dm_os_memory_objects
đó được liên kết thông qua memory_object_address
trường trong cả hai DMV. Đối tượng bộ nhớ này chứa bảng biểu tượng, bộ sưu tập tham số, liên kết đến các đối tượng liên quan, bộ đệm truy cập, bộ đệm siêu dữ liệu TDS và có thể một số mục khác. Gói tổng hợp được chia sẻ giữa các Phiên / Người dùng đang thực hiện cùng một đợt với cùng cài đặt Phiên. Tuy nhiên, một số đối tượng liên quan không được chia sẻ giữa Phiên / Người dùng.
Các gói đã biên dịch cũng có một hoặc nhiều đối tượng phụ thuộc có thể được tìm thấy bằng cách chuyển plan_handle
(trong sys.dm_exec_cached_plans
) vào sys.dm_exec_cached_plan_dependent_objects
DMF. Có hai loại đối tượng phụ thuộc: Kế hoạch thực thi (Đối tượng bộ nhớ = MEMOBJ_EXECUTE ) và Con trỏ (Đối tượng bộ nhớ = MEMOBJ_CURSOREXEC ). Sẽ có 0 hoặc nhiều đối tượng Con trỏ, mỗi đối tượng con trỏ. Cũng sẽ có một hoặc nhiều đối tượng Kế hoạch thực thi, mỗi đối tượng mỗi Người dùng thực hiện cùng một đợt , do đó, các Kế hoạch thực thi không phải làchia sẻ giữa những người dùng. Các gói thực thi chứa tham số thời gian chạy và thông tin biến cục bộ, trạng thái thời gian chạy như câu lệnh hiện đang thực thi, id đối tượng cho các đối tượng được tạo tại thời gian chạy (Tôi giả sử điều này đề cập đến Biến bảng, Bảng tạm thời, Quy trình lưu trữ tạm thời, v.v.) , và có thể các mặt hàng khác.
Mỗi câu lệnh trong một lô nhiều câu lệnh được chứa trong Câu lệnh được biên dịch (Đối tượng bộ nhớ = MEMOBJ_STATEMENT ). Kích thước của mỗi Câu lệnh được biên dịch (nghĩa là pages_in_bytes
) chia cho 1024 phải khớp với các CachedPlanSize="xx"
giá trị của các <QueryPlan>
nút trong kế hoạch XML. Các câu lệnh được biên dịch thường sẽ có một (có thể nhiều hơn?) Các kế hoạch truy vấn thời gian chạy liên quan (Bộ nhớ đối tượng = MEMOBJ_XSTMT ). Cuối cùng, đối với mỗi Kế hoạch truy vấn thời gian chạy là một truy vấn, cần có một Bối cảnh thực thi truy vấn có liên quan (Đối tượng bộ nhớ = MEMOBJ_QUERYEXECCNTXTFORSE ).
Đối với Báo cáo Biên soạn với, lô duy nhất tuyên bố không có Tuyên bố riêng Biên soạn (tức MEMOBJ_STATEMENT ) hoặc thời gian chạy riêng biệt Kế hoạch truy vấn (ví dụ MEMOBJ_XSTMT ) đối tượng. Giá trị cho từng đối tượng đó sẽ được lưu trữ trong đối tượng Kế hoạch tổng hợp chính (ví dụ MEMOBJ_COMPILE_ADHOC ) và trong trường hợp đó, pages_in_bytes
giá trị cho đối tượng chính đó chia cho 1024 phải khớp với CachedPlanSize
kích thước trong <QueryPlan>
nút của kế hoạch XML. Tuy nhiên, các giá trị đó sẽ không bằng nhau trong các lô đa câu lệnh.
Các size_in_bytes
giá trị có thể được rút ra bằng cách tổng hợp các mục trong sys.dm_os_memory_objects
DMV (các mục đã nêu ở trên in đậm), tất cả các liên quan bằng cách dm_os_memory_objects.page_allocator_address
cho rằng Biên soạn kế hoạch. Mẹo để có được giá trị chính xác là trước tiên hãy lấy memory_object_address
từ sys.dm_exec_cached_plans
một Gói tổng hợp cụ thể, sau đó sử dụng giá trị đó để lấy hàng MEMOBJ_COMPILE_ADHOC tương ứng sys.dm_os_memory_objects
dựa trên memory_object_address
trường của nó . Sau đó, lấy page_allocator_address
giá trị từ sys.dm_os_memory_objects
cho hàng đó và sử dụng nó để lấy tất cả các hàng từ sys.dm_os_memory_objects
đó có cùng page_allocator_address
giá trị. (Xin lưu ý rằng kỹ thuật này không hoạt động đối với các loại Đối tượng được lưu trong bộ nhớ cache khác: Parse Tree , Extended Proc , CLR Compiled Proc và CLR Compiled Func.)
Sử dụng memory_object_address
giá trị thu được từ sys.dm_exec_cached_plans
, bạn có thể thấy tất cả các thành phần của Gói tổng hợp thông qua truy vấn sau:
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;
Truy vấn bên dưới liệt kê tất cả các Kế hoạch được biên dịch sys.dm_exec_cached_plans
cùng với Kế hoạch truy vấn và các câu lệnh cho từng lô. Truy vấn trực tiếp ở trên được kết hợp vào truy vấn bên dưới thông qua XML dưới dạng MemoryObjects
trường:
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;
Xin lưu ý rằng:
- các
TotalPlanBytes
lĩnh vực chỉ là một tái tuyên bố của sys.dm_exec_cached_plans.size_in_bytes
lĩnh vực,
- các
AllocatedBytes
lĩnh vực là SUM của các đối tượng bộ nhớ liên quan mà thường phù hợp TotalPlanBytes
(ví dụ size_in_bytes
)
- các
AllocatedBytes
lĩnh vực sẽ thường xuyên được lớn hơn TotalPlanBytes
(ví dụ size_in_bytes
) do tiêu thụ bộ nhớ tăng trong thời gian thực. Điều này dường như xảy ra chủ yếu là do biên dịch lại (điều này hiển nhiên với usecounts
trường hiển thị 1
)
- các
BaseSingleStatementPlanKB
lĩnh vực nên phù hợp với CachedPlanSize
thuộc tính của QueryPlan
nút trong XML, nhưng chỉ khi sử dụng một loạt câu hỏi duy nhất.
- cho lô với nhiều truy vấn, có nên được hàng đánh dấu là
MEMOBJ_STATEMENT
trong sys.dm_os_memory_objects
, một cho mỗi truy vấn. Các pages_in_bytes
lĩnh vực cho những hàng phải phù hợp với từng <QueryPlan>
nút của kế hoạch XML.
Tài nguyên: