DMV のsize_in_bytes
フィールドが、sys.dm_exec_cached_plans
少なくとも「コンパイル済みプラン」に関して、XMLプランのノードのCachedPlanSize
属性よりも大きいのQueryPlan
は、コンパイル済みプランがクエリプランと同じではないためです。コンパイル済みプランは複数のメモリオブジェクトで構成され、それらの合計サイズはsize_in_bytes
フィールドに相当します。そのため、ドキュメントで見つけた「キャッシュオブジェクトによって消費されるバイト数」の説明は正確です。DMVの名前を与えられた「キャッシュオブジェクト」の意味を誤って解釈しやすく、「プラン」という用語には複数の意味があるというだけです。
コンパイル済みプランは、クエリバッチ(つまり、単一のステートメントではない)に関連するさまざまな情報を保持するコンテナであり、それらの1つ(または複数)がクエリプランです。コンパイルされたプランには、MEMOBJ_COMPILE_ADHOCの最上位メモリオブジェクトがあります。これは、両方のDMVのフィールドをsys.dm_os_memory_objects
介してリンクされる行memory_object_address
です。このメモリオブジェクトには、シンボルテーブル、パラメータコレクション、関連オブジェクトへのリンク、アクセサキャッシュ、TDSメタデータキャッシュ、および場合によってはその他のアイテムが含まれます。コンパイルされたプランは、同じセッション設定で同じバッチを実行しているセッション/ユーザー間で共有されます。ただし、一部の関連オブジェクトはセッション/ユーザー間で共有されません。
コンパイル済みプランには、DMFにplan_handle
(in sys.dm_exec_cached_plans
)を渡すことで見つけることができる1つ以上の依存オブジェクトもありますsys.dm_exec_cached_plan_dependent_objects
。依存オブジェクトには、実行可能プラン(メモリオブジェクト= MEMOBJ_EXECUTE)とカーソル(メモリオブジェクト= MEMOBJ_CURSOREXEC)の2つのタイプがあります。各カーソルに1つずつ、0個以上のCursorオブジェクトがあります。また、同じ実行し、各ユーザーごとに1つまたは複数の実行計画は、オブジェクトが存在しますバッチを、したがって実行計画がある、ありませんユーザー間で共有。実行可能プランには、実行時パラメーターとローカル変数情報、現在実行中のステートメントなどの実行時状態、実行時に作成されたオブジェクトのオブジェクトIDが含まれます(これはテーブル変数、一時テーブル、一時ストアドプロシージャなどを指していると思います) 、およびおそらく他のアイテム。
複数ステートメントバッチ内の各ステートメントは、コンパイル済みステートメント(メモリオブジェクト= MEMOBJ_STATEMENT)に含まれています。各コンパイル済みステートメント(つまりpages_in_bytes
)を1024で割ったサイズは、XMLプランのノードのCachedPlanSize="xx"
値と一致する必要<QueryPlan>
があります。コンパイルされたステートメントには、多くの場合、ランタイムクエリプラン(メモリオブジェクト= MEMOBJ_XSTMT)が1つ(おそらくそれ以上)関連付けられています。最後に、クエリであるランタイムクエリプランごとに、関連付けられたクエリ実行コンテキスト(メモリオブジェクト= MEMOBJ_QUERYEXECCNTXTFORSE)が必要です。
コンパイル済みステートメントに関して、単一ステートメントバッチには、別個のコンパイル済みステートメント(つまりMEMOBJ_STATEMENT)または別個のランタイムクエリプラン(つまりMEMOBJ_XSTMT)オブジェクトがありません。これらの各オブジェクトの値は、メインのコンパイル済みプランオブジェクト(つまりMEMOBJ_COMPILE_ADHOC)に格納され、その場合、pages_in_bytes
そのメインオブジェクトの値を1024で割った値がXMLプランのノードのCachedPlanSize
サイズと一致する必要<QueryPlan>
があります。ただし、複数ステートメントのバッチでは、これらの値は一致しません。
このsize_in_bytes
値は、sys.dm_os_memory_objects
DMV(上記の太字の項目)のエントリを合計することで導出できます。これらの項目はすべてdm_os_memory_objects.page_allocator_address
、そのコンパイル済みプランに関連しています。正しい値を取得する秘trickは、最初に特定のコンパイル済みプランのmemory_object_address
from sys.dm_exec_cached_plans
を取得し、それを使用して、そのフィールドに基づいて対応するMEMOBJ_COMPILE_ADHOC行を取得することです。次に、その行の値を取得し、それを使用して同じ値を持つすべての行を取得します。(この手法は、他のキャッシュオブジェクトタイプでは機能しないことに注意してください:Parse Tree、Extended Proc、CLR Compiled Proc、およびCLR Compiled Funcsys.dm_os_memory_objects
memory_object_address
page_allocator_address
sys.dm_os_memory_objects
sys.dm_os_memory_objects
page_allocator_address
)
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
各バッチのクエリプランとステートメントとともに、すべてのコンパイル済みプランをリストします。すぐ上のクエリは、MemoryObjects
フィールドとしてXMLを介して以下のクエリに組み込まれます。
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
フィールドには、一般的に一致して、関連するメモリオブジェクトのSUMであるTotalPlanBytes
(つまりsize_in_bytes
)
- 実行中にメモリ消費が増加するため、
AllocatedBytes
フィールドは時々TotalPlanBytes
(つまりsize_in_bytes
)を超えます。これは、主に再コンパイルが原因で発生するようです(usecounts
フィールドが表示されていることから明らかです1
)
BaseSingleStatementPlanKB
フィールドには、必要があります一致CachedPlanSize
の属性QueryPlan
XML内のノードを、しかし、唯一つのクエリ・バッチを使用した場合。
- 複数のクエリでのバッチのために、とマークされた行があるはず
MEMOBJ_STATEMENT
でsys.dm_os_memory_objects
クエリごとに1、。pages_in_bytes
これらの行のフィールド<QueryPlan>
は、XMLプランの個々のノードと一致する必要があります。
リソース: