连接sys.dm_exec_cached_plans和sys.dm_os_memory_objects的查询,查看有问题的计划,表示pages_in_bytes和max_pages_in_bytes的值为32768(32KB),与缓存的计划大小相匹配.
我不明白的是sys.dm_exec_cached_plans.size_in_bytes中的值,即49152(48KB)代表的值.我已经在所有这些列上阅读了BOL,特别是size_in_bytes,其中说:
“Number of bytes consumed by the cache object.“
我无法掌握最后一点拼图,了解它的真正含义.
我知道所有运算符(不是讨论用于排序和散列的额外内存授权)需要一定数量的固定内存,存储状态,进行计算等,这与优化计划一起存储在缓存中,但在哪里?
所以,我的问题是:
> size_in_bytes的真正含义是什么
>为什么它的值高于“缓存计划大小”?
>保留所有运算符/迭代器的固定内存量在哪里,是否具有“缓存计划大小”(在我的示例中为32Kb)或其他任何位置?
我知道他们是具有不同功能的不同DMV,但它们是相关的. sys.dm_exec_cached_plans中的已编译(缓存)计划加入memory_object_address列上的sys.dm_os_memory_objects.我在这里发布问题的原因是,我正在寻求帮助,理解如何解释DMV及其列.
如果size_in_bytes是缓存的计划大小,为什么sql Server在实际执行计划中说另一个值?
新查询,新号码:
>实际计划
>缓存计划大小16KB
> CompileMemory 96KB
> DMV:
> 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)
解决方法
编译计划是容纳与查询批次相关的各种信息(即,不仅仅是单个语句)的容器,其中一个(或多个)是查询计划.编译计划有一个MEMOBJ_COMPILE_ADHOC的顶级内存对象,它是sys.dm_os_memory_objects中通过两个DMV中的memory_object_address字段链接的行.此内存对象包含符号表,参数集合,相关对象的链接,访问者缓存,TDS元数据缓存以及可能的其他一些项目.编译计划在使用相同会话设置执行相同批处理的会话/用户之间共享.但是,会话/用户之间不共享某些相关对象.
编译计划还有一个或多个依赖对象,可以通过将plan_handle(在sys.dm_exec_cached_plans中)传递到sys.dm_exec_cached_plan_dependent_objects DMF中来找到.有两种类型的依赖对象:可执行计划(Memory Object = MEMOBJ_EXECUTE)和Cursor(Memory Object = MEMOBJ_CURSOREXEC).将有0个或更多Cursor对象,每个光标一个.还将有一个或多个可执行计划对象,每个用户执行同一批处理一个对象,因此用户之间不共享可执行计划.可执行计划包含运行时参数和本地变量信息,运行时状态(如当前正在执行的语句),运行时创建的对象的对象ID(我假设这是指表变量,临时表,临时存储过程等),可能还有其他项目.
多语句批处理中的每个语句都包含在编译语句(Memory Object = MEMOBJ_STATEMENT)中.每个编译语句(即pages_in_bytes)的大小除以1024应该与< QueryPlan>的CachedPlanSize =“xx”值匹配. XML计划中的节点.编译语句通常会有一个(可能更多?)关联的运行时查询计划(Memory Object = MEMOBJ_XSTMT).最后,对于作为查询的每个运行时查询计划,应该存在关联的查询执行上下文(Memory Object = MEMOBJ_QUERYEXECCNTXTFORSE).
对于编译语句,单语句批处理没有单独的编译语句(即MEMOBJ_STATEMENT)或单独的运行时查询计划(即MEMOBJ_XSTMT)对象.每个对象的值将存储在主编译计划对象(即MEMOBJ_COMPILE_ADHOC)中,在这种情况下,该主对象的pages_in_bytes值除以1024应与< QueryPlan>中的CachedPlanSize大小匹配. XML计划的节点.但是,这些值不会等同于多语句批次.
size_in_bytes值可以通过汇总sys.dm_os_memory_objects DMV中的条目(上面以粗体表示的项目)来导出,所有条目都与该编译计划的dm_os_memory_objects.page_allocator_address相关.获取正确值的技巧是首先从sys.dm_exec_cached_plans获取特定编译计划的memory_object_address,然后根据其memory_object_address字段使用该行从sys.dm_os_memory_objects获取相应的MEMOBJ_COMPILE_ADHOC行.然后,从sys.dm_os_memory_objects中获取该行的page_allocator_address值,并使用它从sys.dm_os_memory_objects中获取具有相同page_allocator_address值的所有行. (请注意,此技术不适用于其他缓存对象类型:Parse Tree,Extended Proc,CLR Compiled Proc和CLR Compiled Func.)
使用从sys.dm_exec_cached_plans获取的memory_object_address值,您可以通过以下查询查看编译计划的所有组件:
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字段合并到下面的查询中:
请注意:
> TotalPlanBytes字段只是sys.dm_exec_cached_plans.size_in_bytes字段的重新声明,
> AllocatedBytes字段是相关内存对象的SUM,通常与TotalPlanBytes匹配(即size_in_bytes)
>由于执行期间内存消耗增加,AllocatedBytes字段偶尔会大于TotalPlanBytes(即size_in_bytes).这似乎主要是由于重新编译(这应该是显示1的usecounts字段显而易见)
> BaseSingleStatementPlanKB字段应与XML中QueryPlan节点的CachedPlanSize属性匹配,但仅限于使用单个查询批处理时.
>对于具有多个查询的批处理,sys.dm_os_memory_objects中应该有标记为MEMOBJ_STATEMENT的行,每个查询对应一行.这些行的pages_in_bytes字段应与单个< QueryPlan>匹配. XML计划的节点.资源:
> What are the different cached objects in the plan cache?
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],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.[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 = 0x
> 1.0 Structure of the Plan Cache and Types of Cached Objects
> 2.0 Sql_Handle and Plan_Handle Explained
> sys.dm_exec_cached_plans的MSDN页面DECLARE @CompiledPlanAddress VARBINARY(8) = 0x00000001DC4A4060; SELECT obj.memory_object_address,obj.pages_in_bytes;D0031CD572910529CE001000000xxxxxxxxDECLARE @CompiledPlanAddress VARBINARY(8) = 0x00000001DC4A4060; SELECT obj.memory_object_address,obj.pages_in_bytes;
ORDER BY cplan.objtype,cplan.plan_handle;