Плануйте розмір кешу та зарезервовану пам'ять


18

Під час запуску запиту, включаючи фактичний план виконання, кореневий оператор ( SELECT) повідомляє мені, що розмір кешованого плану становить 32 КБ.

Запит, який приєднується sys.dm_exec_cached_plansі sys.dm_os_memory_objects, дивлячись на відповідний план, каже, що значення для pages_in_bytesта max_pages_in_bytesє 32768 (32 КБ), що відповідає розміру кешованого плану.

Що я не розумію, це те, на чому позначається значення sys.dm_exec_cached_plans.size_in_bytes, яке становить 49152 (48 КБ). Я читав BOL у всіх цих стовпцях, і особливо там, size_in_bytesде написано:

" Кількість байтів, спожитих об'єктом кешу. "

Я не можу скласти останній шматочок головоломки на місце, щоб зрозуміти, що це насправді означає.

Я знаю, що всім операторам (не кажучи про додатковий грамот пам’яті, що використовується для сортування та хешів) потрібен деякий обсяг фіксованої пам’яті, для зберігання стану, проведення обчислень тощо, який зберігається з оптимізованим планом у кеші, але де?

Отже, мої запитання:

  • Що size_in_bytesнасправді означає
  • Чому це значення вище, ніж "Розмір кешованого плану"?
  • Де зарезервований фіксований об'єм пам'яті для всіх операторів / ітераторів, це з "розміром кешованого плану" (32 кб в моєму прикладі) чи деінде?

Я знаю, що вони різні DMV з різними функціями, але вони пов'язані між собою. Складені (кешовані) плани sys.dm_exec_cached_plansприєднуються sys.dm_os_memory_objectsдо memory_object_addressстовпця. Причина, яку я розміщую тут, полягає в тому, що я прошу допомоги з цього приводу, розуміючи, як інтерпретувати DMV та їх колонки.

Якщо size_in_bytesрозмір кешованого плану, чому SQL Server говорить інше значення у фактичному плані виконання?

Новий запит, нові номери:

  • Фактичний план
    • Розмір кешованого плану 16 КБ
    • CompileMemory 96KB
  • DMV:
    • sys.dm_exec_cached_plans.size_in_bytes 24 КБ
    • sys.dm_os_memory_objects.pages_in_bytes, .max_pages_in_bytes 16 КБ.

Також зауважте, що цей запит не потребує додаткових дозволів на пам'ять для сортування та хеш-операцій.

Microsoft SQL Server 2012 - 11.0.5343.0 (X64)

Відповіді:


12

Причина того, що size_in_bytesполе sys.dm_exec_cached_plansDMV, принаймні, з точки зору "Складені плани", є більшим, ніж CachedPlanSizeатрибут QueryPlanвузла в плані XML, тому що Скомпільований план - це не те саме, що план запитів. Складений план складається з декількох об'єктів пам'яті, комбінований розмір яких дорівнює size_in_bytesполі. Отже, опис " Кількість байтів, спожитих об'єктом кешу ", який ви знайшли в документації, є точним; просто неправильно трактувати те, що розуміється під "об'єктом кешу", даючи назву DMV, і що термін "план" має багато значень.

Складений план - це контейнер, в якому зберігаються різні фрагменти інформації, що стосуються партії запитів (тобто, не лише одне твердження), один (або більше) з цих фрагментів є планом (ими) запитів. У складених планах є об'єкт пам'яті верхнього рівня MEMOBJ_COMPILE_ADHOC, який є рядком sys.dm_os_memory_objects, пов'язаним через memory_object_addressполе в обох DMV. Цей об'єкт пам'яті містить таблицю символів, збір параметрів, посилання на пов'язані об'єкти, кеш-пам'ять аксесуара, кеш метаданих TDS та, можливо, деякі інші елементи. Складені плани поділяються між сесіями / користувачами, які виконують ту саму партію з тими ж налаштуваннями сесії. Однак деякі пов'язані об'єкти не діляться між сесіями / користувачами.

У складених планах також є один або більше залежних об'єктів, які можна знайти, передавши plan_handlesys.dm_exec_cached_plans) у sys.dm_exec_cached_plan_dependent_objectsDMF. Існує два типи залежних об'єктів: виконуваний план (об'єкт пам'яті = 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_objectsDMV (пункти зазначено вище жирним шрифтом), все пов'язані 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.

Ресурси:

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.