キャッシュサイズと予約メモリを計画する


18

実際の実行計画を含むクエリを実行すると、ルート演算子(SELECT)からキャッシュされた計画サイズが32KBであることが通知されます。

sys.dm_exec_cached_plansとを結合するクエリはsys.dm_os_memory_objects、問題のプランを見て、との値が32768(32KB)であり、キャッシュされたプランのサイズと一致するpages_in_bytesと言いますmax_pages_in_bytes

私が理解していないのは、の値sys.dm_exec_cached_plans.size_in_bytesが49152(48KB)の略であるということです。これらすべてのコラムでBOLを読みました。特に次のようsize_in_bytesに述べています。

キャッシュオブジェクトが消費したバイト数。

それが本当に何を意味するのか理解するために、私はパズルの最後の部分を配置することはできません。

すべての演算子(並べ替えとハッシュに使用される追加のメモリ許可については説明しません)は、キャッシュに最適化されたプランで保存される状態の保存、計算の実行などのために、ある程度の固定メモリを必要としますが、どこにありますか?

だから、私の質問は:

  • size_in_bytes本当にどういう意味ですか
  • 「キャッシュされた計画サイズ」よりも高い値になるのはなぜですか?
  • すべての演算子/イテレータのメモリの固定量はどこに予約されていますか、「キャッシュされたプランサイズ」(この例では32Kb)ですか、それとも他の場所ですか?

私はそれらが異なる機能を持つ異なるDMVであることを知っていますが、それらは関連しています。でコンパイルされた(キャッシュされた)計画sys.dm_exec_cached_plans参加するsys.dm_os_memory_objects上でmemory_object_addressのカラム。私がここに質問を投稿する理由は、私がこれについて助けを求めて、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)

回答:


12

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_objectsDMV(上記の太字の項目)のエントリを合計することで導出できます。これらの項目はすべてdm_os_memory_objects.page_allocator_address、そのコンパイル済みプランに関連しています。正しい値を取得する秘trickは、最初に特定のコンパイル済みプランのmemory_object_addressfrom sys.dm_exec_cached_plansを取得し、それを使用して、そのフィールドに基づいて対応するMEMOBJ_COMPILE_ADHOC行を取得することです。次に、その行の値を取得し、それを使用して同じ値を持つすべての行を取得します。(この手法は、他のキャッシュオブジェクトタイプでは機能しないことに注意してください:Parse TreeExtended ProcCLR Compiled Proc、およびCLR Compiled Funcsys.dm_os_memory_objectsmemory_object_addresspage_allocator_addresssys.dm_os_memory_objectssys.dm_os_memory_objectspage_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の属性QueryPlanXML内のノードを、しかし、唯一つのクエリ・バッチを使用した場合。
  • 複数のクエリでのバッチのために、とマークされた行があるはずMEMOBJ_STATEMENTsys.dm_os_memory_objectsクエリごとに1、。pages_in_bytesこれらの行のフィールド<QueryPlan>は、XMLプランの個々のノードと一致する必要があります。

リソース:

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.