캐시 크기 및 예약 된 메모리 계획


18

실제 실행 계획을 포함하여 쿼리를 실행할 때 루트 연산자 ( SELECT)는 캐시 된 계획 크기 가 32KB 임을 알려줍니다 .

조인 쿼리 sys.dm_exec_cached_planssys.dm_os_memory_objects해당 계획을 찾고, 그 값 말한다 pages_in_bytesmax_pages_in_bytes캐시 된 계획의 크기와 일치 32768 (32킬로바이트를)입니다.

내가 이해하지 못하는 것은의 값인 sys.dm_exec_cached_plans.size_in_bytes49152 (48KB)의 의미입니다. 이 모든 열에서 BOL을 읽었으며 특히 다음과 size_in_bytes같이 말합니다.

" 캐시 개체가 소비 한 바이트 수 "

나는 그것이 의미하는 바를 이해하기 위해 퍼즐의 마지막 부분을 얻을 수 없습니다.

모든 연산자 (정렬 및 해시에 사용되는 추가 메모리 부여에 대해 이야기하지 않음)에는 캐시에 최적화 된 계획으로 저장된 상태를 저장하고 계산하는 등 고정 메모리가 어느 정도 필요하다는 것을 알고 있습니다.

그래서 내 질문은 :

  • size_in_bytes실제로 무엇을 의미 하는가
  • 왜 "Cached plan size"보다 높은 값입니까?
  • 모든 운영자 / 반복자에 대해 고정 된 메모리 양이 예약되어있는 곳은 "캐시 된 계획 크기"(예 : 32Kb) 또는 다른 곳입니까?

나는 그들이 다른 기능을 가진 다른 DMV라는 것을 알고 있지만 관련되어 있습니다. 의 컴파일 (캐시) 계획은 sys.dm_exec_cached_plans조인 sys.dm_os_memory_objectsmemory_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필드가 XML 계획 의 노드 속성 sys.dm_exec_cached_plans보다 큰 이유는 컴파일 된 계획이 쿼리 계획과 동일하지 않기 때문입니다. 컴파일 된 계획은 여러 메모리 객체로 구성되며, 결합 된 크기는 필드 와 같습니다 . 따라서 설명서에서 찾은 " 캐시 개체가 소비 한 바이트 수 "에 대한 설명은 정확합니다. DMV의 이름이 주어지면 "캐시 객체"의 의미를 잘못 해석하기 쉽고 "계획"이라는 용어는 여러 가지 의미를 갖습니다.CachedPlanSizeQueryPlansize_in_bytes

컴파일 된 계획은 쿼리 배치 와 관련된 다양한 정보 (예 : 단일 명령문이 아닌) 를 보유하는 컨테이너로 , 그 중 하나 이상이 쿼리 계획입니다. 컴파일 된 계획에는 MEMOBJ_COMPILE_ADHOC의 최상위 메모리 개체가 있으며 ,이 행 은 두 DMV sys.dm_os_memory_objectsmemory_object_address필드를 통해 연결됩니다 . 이 메모리 개체에는 심볼 테이블, 매개 변수 수집, 관련 개체에 대한 링크, 접근 자 캐시, TDS 메타 데이터 캐시 및 기타 항목이 포함됩니다. 컴파일 된 계획은 동일한 세션 설정으로 동일한 배치 를 실행하는 세션 / 사용자간에 공유 됩니다. 그러나 일부 관련 개체는 세션 / 사용자간에 공유 되지 않습니다 .

컴파일 된 계획에는 또한 plan_handle(in sys.dm_exec_cached_plans)을 sys.dm_exec_cached_plan_dependent_objectsDMF 로 전달하여 찾을 수있는 하나 이상의 종속 개체가 있습니다 . 종속 오브젝트에는 실행 계획 (메모리 오브젝트 = MEMOBJ_EXECUTE ) 및 커서 (메모리 오브젝트 = MEMOBJ_CURSOREXEC )의 두 가지 유형이 있습니다 . 각 커서 당 하나씩 0 개 이상의 Cursor 객체가 있습니다. 또한 동일한 배치를 실행하는 각 사용자 당 하나씩 하나 이상의 실행 가능한 계획 개체가 있으므로 실행 가능한 계획은 없습니다.사용자간에 공유됩니다. 실행 계획에는 런타임 매개 변수 및 로컬 변수 정보, 현재 실행중인 명령문과 같은 런타임 상태, 런타임에 작성된 오브젝트의 오브젝트 ID가 포함됩니다 (테이블 변수, 임시 테이블, 임시 저장 프로 시저 등을 가정합니다) 및 기타 항목 일 수 있습니다.

다중 문 일괄 처리 내의 각 문 은 컴파일 된 문 (메모리 개체 = 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로 나눈 값 은 XML 계획 CachedPlanSize<QueryPlan>노드 크기 와 일치해야합니다 . 그러나이 값은 다중 문 배치에서 동일하지 않습니다.


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_addresssys.dm_os_memory_objects을 가져 와서 sys.dm_os_memory_objects해당 page_allocator_address값 을 가진 모든 행을 가져 옵니다 . (이 기술은 다른 캐싱 된 객체 유형 인 구문 분석 트리 , 확장 된 Proc , CLR 컴파일 된 ProcCLR 컴파일 된 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의 속성 QueryPlanXML에서 노드를하지만, 하나의 쿼리 일괄 처리를 사용하는 경우.
  • 여러 쿼리와 배치에 대한 행이 거기 표시되어야 MEMOBJ_STATEMENT에서 sys.dm_os_memory_objects각 쿼리에 대해 하나. pages_in_bytes이 행 의 필드 <QueryPlan>는 XML 계획 의 개별 노드 와 일치해야합니다 .

자원:

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.