Причина того, що size_in_bytes
поле sys.dm_exec_cached_plans
DMV, принаймні, з точки зору "Складені плани", є більшим, ніж CachedPlanSize
атрибут QueryPlan
вузла в плані XML, тому що Скомпільований план - це не те саме, що план запитів. Складений план складається з декількох об'єктів пам'яті, комбінований розмір яких дорівнює size_in_bytes
полі. Отже, опис " Кількість байтів, спожитих об'єктом кешу ", який ви знайшли в документації, є точним; просто неправильно трактувати те, що розуміється під "об'єктом кешу", даючи назву DMV, і що термін "план" має багато значень.
Складений план - це контейнер, в якому зберігаються різні фрагменти інформації, що стосуються партії запитів (тобто, не лише одне твердження), один (або більше) з цих фрагментів є планом (ими) запитів. У складених планах є об'єкт пам'яті верхнього рівня MEMOBJ_COMPILE_ADHOC, який є рядком sys.dm_os_memory_objects
, пов'язаним через memory_object_address
поле в обох DMV. Цей об'єкт пам'яті містить таблицю символів, збір параметрів, посилання на пов'язані об'єкти, кеш-пам'ять аксесуара, кеш метаданих 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 ). Значення для кожного з цих об'єктів буде зберігатися в головному об'єкті Compiled Plan (тобто 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_ADHOCsys.dm_os_memory_objects
на основі його memory_object_address
поля. Потім перейміть page_allocator_address
значення sys.dm_os_memory_objects
для цього рядка та використовуйте його, щоб схопити всі рядки з sys.dm_os_memory_objects
цього page_allocator_address
значення. (Будь ласка , зверніть увагу , що цей метод не працює для інших кешованих типів об'єктів: дерево розбору , Extended Proc , CLR Укладач Proc і CLR Укладач 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.
Ресурси: