Планирование размера кеша и зарезервированной памяти

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_bytes49152 (48 КБ). Я прочитал BOL на всех этих столбцах, и особенно, size_in_bytesчто говорит:

Msgstr " Количество байтов, использованных объектом кеша. "

Я не могу понять эту последнюю часть головоломки, чтобы понять, что это на самом деле означает.

Я знаю, что всем операторам (не говоря о дополнительном предоставлении памяти, используемом для сортировок и хэшей) требуется некоторый объем фиксированной памяти для хранения состояния, выполнения вычислений и т. Д., Который хранится с оптимизированным планом в кеше, но где?

Итак, мои вопросы:

  • Что на size_in_bytesсамом деле значит
  • Почему это значение выше, чем «Размер кэшированного плана»?
  • Где зарезервирован фиксированный объем памяти для всех операторов / итераторов, с "размером кэшированного плана" (в моем примере 32Kb) или где-нибудь еще?

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

Если size_in_bytesразмер кэшированного плана, почему SQL Server говорит другое значение в фактическом плане выполнения?

Новый запрос, новые номера:

  • Актуальный план
    • Размер кэшированного плана 16 КБ
    • CompileMemory 96KB
  • DMVs:
    • sys.dm_exec_cached_plans.size_in_bytes 24KB
    • sys.dm_os_memory_objects.pages_in_bytes, .max_pages_in_bytes 16KB.

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

Microsoft SQL Server 2012 - 11.0.5343.0 (X64)
GordonLiddy
источник

Ответы:

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 или более объектов Cursor, по одному на каждый курсор. Также будет один или несколько объектов исполняемого плана, по одному на каждого пользователя, выполняющего тот же пакет , следовательно, исполняемые планы не являютсяделится между пользователями. Исполняемые планы содержат параметр времени выполнения и информацию о локальной переменной, состояние времени выполнения, такое как текущий выполняемый оператор, идентификаторы объектов для объектов, созданных во время выполнения (я предполагаю, что это относится к переменным таблиц, временным таблицам, временным хранимым процедурам и т. Д.) и, возможно, другие предметы.

Каждый оператор в пакете с несколькими операторами содержится в скомпилированном операторе (объект памяти = 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_objectsDMV (пункты отмечено выше жирным шрифтом), все связаны 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значением. (Пожалуйста , обратите внимание , что этот метод не работает для других кэшированных типов объектов: дерево разбора , 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.

Ресурсы:

Соломон Руцкий
источник