Pianificare le dimensioni della cache e la memoria riservata


18

Quando si esegue una query che include il piano di esecuzione effettivo, l'operatore root ( SELECT) mi informa che la dimensione del piano memorizzato nella cache è 32 KB .

Una query che unisce sys.dm_exec_cached_planse sys.dm_os_memory_objects, osservando il piano in questione, afferma che i valori per pages_in_bytese max_pages_in_bytessono 32768 (32 KB), che corrisponde alla dimensione del piano memorizzato nella cache.

Quello che non capisco è quale sia il valore sys.dm_exec_cached_plans.size_in_bytes, che è 49152 (48KB). Ho letto BOL su tutte queste colonne, e in particolare size_in_bytesche dice:

" Numero di byte consumati dall'oggetto cache. "

Non riesco a mettere in atto l'ultimo pezzo del puzzle, per capire cosa significhi davvero.

So che tutti gli operatori (non parlando della concessione di memoria aggiuntiva utilizzata per ordinamenti e hash) richiedono una certa quantità di memoria fissa, per memorizzare lo stato, eseguire calcoli ecc., Che viene archiviato con il piano ottimizzato nella cache, ma dove?

Quindi, le mie domande sono:

  • Cosa significa size_in_bytesveramente
  • Perché ha un valore superiore a "Dimensione piano cache"?
  • Dove è riservata la quantità fissa di memoria per tutti gli operatori / iteratori, è con la "dimensione del piano memorizzato nella cache" (32 KB nel mio esempio) o in qualsiasi altro luogo?

So che sono DMV diversi con funzioni diverse, ma sono correlati. I piani compilati (memorizzati nella cache) si sys.dm_exec_cached_plansuniscono sys.dm_os_memory_objectsalla memory_object_addresscolonna. Il motivo per cui pubblico qui le domande è che sto chiedendo aiuto su questo, capendo come interpretare i DMV e le loro colonne.

Se size_in_bytesè la dimensione del piano memorizzato nella cache, perché SQL Server indica un altro valore nel piano di esecuzione effettivo?

Nuova query, nuovi numeri:

  • Piano reale
    • Dimensione piano cache 16 KB
    • 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.

Inoltre, tieni presente che questa query non richiede alcuna concessione di memoria aggiuntiva per operazioni di ordinamento e hash.

Microsoft SQL Server 2012 - 11.0.5343.0 (X64)

Risposte:


12

Il motivo per cui il size_in_bytescampo del sys.dm_exec_cached_plansDMV, almeno in termini di "Piani compilati", è più grande CachedPlanSizedell'attributo del QueryPlannodo nel piano XML è perché un piano compilato non è la stessa cosa di un piano di query. Un piano compilato è composto da più oggetti memoria, la cui dimensione combinata corrisponde al size_in_bytescampo. Pertanto, la descrizione di " Numero di byte consumati dall'oggetto cache " che hai trovato nella documentazione è accurata; è solo che è facile interpretare erroneamente cosa si intende per "oggetto cache" dato il nome del DMV e che il termine "piano" ha più significati.

Un piano compilato è un contenitore che contiene varie informazioni relative al batch di query (ovvero non solo una singola istruzione), uno (o più) di quei pezzi che sono i piani di query. I piani compilati hanno un oggetto memoria di livello superiore di MEMOBJ_COMPILE_ADHOC che è la riga in sys.dm_os_memory_objectscui è collegata tramite il memory_object_addresscampo in entrambi i DMV. Questo oggetto memoria contiene la tabella dei simboli, la raccolta dei parametri, i collegamenti agli oggetti correlati, la cache degli accessori, la cache dei metadati TDS e possibilmente alcuni altri elementi. I piani compilati sono condivisi tra sessioni / utenti che eseguono lo stesso batch con le stesse impostazioni di sessione. Tuttavia, alcuni oggetti correlati non sono condivisi tra Sessioni / Utenti.

I piani compilati hanno anche uno o più oggetti dipendenti che possono essere trovati passando il plan_handle(in sys.dm_exec_cached_plans) nel sys.dm_exec_cached_plan_dependent_objectsDMF. Esistono due tipi di oggetti dipendenti: Piano eseguibile (Oggetto memoria = MEMOBJ_EXECUTE ) e Cursore (Oggetto memoria = MEMOBJ_CURSOREXEC ). Ci saranno 0 o più oggetti cursore, uno per ogni cursore. Ci saranno anche uno o più oggetti del piano eseguibile, uno per ogni utente che esegue lo stesso batch , quindi i piani eseguibili non sonocondiviso tra utenti. I piani eseguibili contengono i parametri di runtime e le informazioni sulla variabile locale, lo stato di runtime come l'istruzione attualmente in esecuzione, gli ID oggetto per gli oggetti creati in fase di runtime (suppongo che si riferisca a variabili di tabella, tabelle temporanee, stored procedure temporanee, ecc.) e possibilmente altri elementi.

Ogni istruzione all'interno di un batch multiistruzione è contenuta in un'istruzione compilata (oggetto memoria = MEMOBJ_STATEMENT ). La dimensione di ciascuna istruzione compilata (ovvero pages_in_bytes) divisa per 1024 dovrebbe corrispondere ai CachedPlanSize="xx"valori dei <QueryPlan>nodi nel piano XML. Le istruzioni compilate avranno spesso uno (forse più?) Piani di query di runtime associati (Oggetto memoria = MEMOBJ_XSTMT ). Infine, per ogni piano di query di runtime che è una query, dovrebbe essere associato un contesto di esecuzione della query (oggetto memoria = MEMOBJ_QUERYEXECCNTXTFORSE ).

Rispetto alle istruzioni compilate, i batch a istruzione singola non hanno oggetti istruzione compilata separati (ovvero MEMOBJ_STATEMENT ) o piani di query runtime separati (ovvero MEMOBJ_XSTMT ). Il valore per ciascuno di tali oggetti verrà archiviato nell'oggetto principale del piano compilato (ovvero MEMOBJ_COMPILE_ADHOC ) e, in tal caso, il pages_in_bytesvalore per quell'oggetto principale diviso per 1024 dovrebbe corrispondere alla CachedPlanSizedimensione nel <QueryPlan>nodo del piano XML. Tali valori non equivarranno, tuttavia, in batch multiistruzione.


Il size_in_bytesvalore può essere derivato sommando le voci nel sys.dm_os_memory_objectsDMV (gli elementi sopra indicati in grassetto), tutti correlati dm_os_memory_objects.page_allocator_addressper quel Piano compilato. Il trucco per ottenere il valore corretto è innanzitutto ottenere il memory_object_addressda sys.dm_exec_cached_plansper un particolare piano compilato, quindi utilizzarlo per ottenere la riga MEMOBJ_COMPILE_ADHOC corrispondente in sys.dm_os_memory_objectsbase al relativo memory_object_addresscampo. Quindi, prendi il page_allocator_addressvalore sys.dm_os_memory_objectsper quella riga e usalo per prendere tutte le righe sys.dm_os_memory_objectsche hanno lo stesso page_allocator_addressvalore. (Si noti che questa tecnica non funziona con gli altri tipi di oggetti memorizzati nella cache: Parse Tree , Extended Proc , CLR Compiled Proc e CLR Compiled Func.)

Utilizzando il memory_object_addressvalore ottenuto da sys.dm_exec_cached_plans, è possibile visualizzare tutti i componenti del piano compilato tramite la seguente query:

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;

La query seguente elenca tutti i piani compilati sys.dm_exec_cached_plansinsieme al piano di query e alle dichiarazioni per ciascun batch. La query direttamente sopra è incorporata nella query seguente tramite XML come MemoryObjectscampo:

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;

Si prega di notare che:

  • il TotalPlanBytescampo è solo una ri-dichiarazione del sys.dm_exec_cached_plans.size_in_bytescampo,
  • il AllocatedBytescampo è la SOMMA degli oggetti di memoria correlati che corrisponde tipicamente TotalPlanBytes(cioè size_in_bytes)
  • il AllocatedBytescampo sarà occasionalmente maggiore di TotalPlanBytes(cioè size_in_bytes) a causa dell'aumento del consumo di memoria durante l'esecuzione. Questo sembra accadere principalmente a causa della ricompilazione (che dovrebbe essere evidente con il usecountscampo che mostra 1)
  • il BaseSingleStatementPlanKBcampo deve corrispondere CachedPlanSizeall'attributo del QueryPlannodo nell'XML, ma solo quando si utilizza un singolo batch di query.
  • per i batch con più query, devono essere presenti righe contrassegnate come MEMOBJ_STATEMENTin sys.dm_os_memory_objects, una per ogni query. Il pages_in_bytescampo per queste righe deve corrispondere ai singoli <QueryPlan>nodi del piano XML.

risorse:

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.