Alasan bahwa size_in_bytes
bidang sys.dm_exec_cached_plans
DMV, setidaknya dalam hal "Paket yang Dikompilasi", lebih besar dari CachedPlanSize
atribut QueryPlan
simpul dalam paket XML adalah karena Paket yang Dikompilasi tidak sama dengan Paket Kueri. Paket Kompilasi terdiri dari beberapa Objek Memori, ukuran gabungan yang setara dengan size_in_bytes
bidang. Jadi, deskripsi " Jumlah byte yang dikonsumsi oleh objek cache " yang Anda temukan dalam dokumentasi itu akurat; hanya saja mudah untuk salah menafsirkan apa yang dimaksud dengan "objek cache" yang diberi nama DMV dan bahwa istilah "rencana" memiliki banyak arti.
Rencana yang Dikompilasi adalah wadah yang menampung berbagai informasi yang terkait dengan kumpulan kueri (yaitu, bukan hanya satu pernyataan), satu (atau lebih) dari bagian-bagian itu yang menjadi rencana kueri. Paket yang Dikompilasi memiliki Objek Memori tingkat atas dari MEMOBJ_COMPILE_ADHOC yang merupakan baris dalam sys.dm_os_memory_objects
yang ditautkan melalui memory_object_address
bidang di kedua DMV. Objek Memori ini berisi tabel simbol, pengumpulan parameter, tautan ke objek terkait, cache accessor, cache metadata TDS, dan mungkin beberapa item lainnya. Paket yang Dikompilasi dibagi di antara Sesi / Pengguna yang menjalankan batch yang sama dengan pengaturan Sesi yang sama. Namun, beberapa objek terkait tidak dibagi antara Sesi / Pengguna.
Rencana yang Dikompilasi juga memiliki satu atau lebih objek bergantung yang dapat ditemukan dengan melewatkan plan_handle
(dalam sys.dm_exec_cached_plans
) ke dalam sys.dm_exec_cached_plan_dependent_objects
DMF. Ada dua jenis objek dependen: Executable Plan (Memory Object = MEMOBJ_EXECUTE ) dan Cursor (Memory Object = MEMOBJ_CURSOREXEC ). Akan ada 0 atau lebih objek kursor, satu per setiap kursor. Juga akan ada satu atau lebih objek Rencana yang Dapat Dieksekusi, satu per setiap Pengguna yang menjalankan batch yang sama , karenanya Paket yang Dapat Dieksekusi tidakdibagikan antara Pengguna. Paket yang Dapat Dieksekusi berisi parameter run-time dan info variabel lokal, status run-time seperti pernyataan yang sedang dieksekusi, id objek untuk objek yang dibuat saat run-time (saya berasumsi ini merujuk pada Tabel Variabel, Tabel Sementara, Prosedur Stored Sementara, dll) , dan mungkin item lainnya.
Setiap pernyataan dalam kumpulan multi-pernyataan terkandung dalam Pernyataan Terkompilasi (Obyek Memori = MEMOBJ_STATEMENT ). Ukuran setiap Pernyataan Terkompilasi (yaitu pages_in_bytes
) dibagi 1024 harus cocok dengan CachedPlanSize="xx"
nilai - nilai <QueryPlan>
node dalam rencana XML. Laporan yang dikompilasi akan sering memiliki satu (mungkin lebih?) Rencana Kueri runtime terkait (Memory Object = MEMOBJ_XSTMT ). Akhirnya, untuk setiap Rencana Kueri runtime yang merupakan kueri, harus ada Konteks Eksekusi Kueri yang terkait (Obyek Memori = MEMOBJ_QUERYEXECCNTXTFORSE ).
Sehubungan dengan Pernyataan Kompilasi, kumpulan pernyataan tunggal tidak memiliki Pernyataan Terkompilasi terpisah (yaitu MEMOBJ_STATEMENT ) atau objek Rencana runtime terpisah (yaitu MEMOBJ_XSTMT ) objek. Nilai untuk masing-masing objek tersebut akan disimpan di objek Paket Kompilasi utama (yaitu MEMOBJ_COMPILE_ADHOC ), dan dalam hal itu, pages_in_bytes
nilai untuk objek utama dibagi 1024 harus cocok dengan CachedPlanSize
ukuran di <QueryPlan>
simpul rencana XML. Nilai-nilai itu tidak akan menyamakan, dalam batch multi-pernyataan.
The size_in_bytes
nilai dapat diturunkan dengan menjumlahkan entri di sys.dm_os_memory_objects
DMV (item disebutkan di atas dalam huruf tebal), semua yang berhubungan dengan dm_os_memory_objects.page_allocator_address
untuk itu Disusun Rencana. Trik untuk mendapatkan nilai yang benar adalah dengan terlebih dahulu mendapatkan memory_object_address
dari sys.dm_exec_cached_plans
untuk Paket Kompilasi tertentu, kemudian menggunakannya untuk mendapatkan baris MEMOBJ_COMPILE_ADHOC yang sesuai dari sys.dm_os_memory_objects
berdasarkan memory_object_address
bidangnya. Lalu, ambil page_allocator_address
nilai dari sys.dm_os_memory_objects
untuk baris itu, dan gunakan untuk mengambil semua baris dari sys.dm_os_memory_objects
yang memiliki nilai yang sama page_allocator_address
. (Harap dicatat bahwa teknik ini tidak berfungsi untuk jenis Objek Cached lainnya: Parse Tree , Extended Proc , CLR Compiled Proc , dan CLR Compiled Func.)
Dengan menggunakan memory_object_address
nilai yang diperoleh dari sys.dm_exec_cached_plans
, Anda dapat melihat semua komponen dari Paket yang Dikompilasi melalui kueri berikut:
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;
Kueri di bawah ini mencantumkan semua Paket yang Dikompilasi sys.dm_exec_cached_plans
bersama dengan Rencana Kueri dan pernyataan untuk setiap kumpulan. Kueri langsung di atas dimasukkan ke dalam kueri di bawah ini melalui XML sebagai MemoryObjects
bidang:
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;
Harap dicatat bahwa:
- yang
TotalPlanBytes
bidang hanya re-pernyataan dari sys.dm_exec_cached_plans.size_in_bytes
lapangan,
- yang
AllocatedBytes
bidang adalah SUM dari obyek memori terkait yang biasanya cocok TotalPlanBytes
(yaitu size_in_bytes
)
- yang
AllocatedBytes
lapangan akan sesekali lebih besar dari TotalPlanBytes
(yaitu size_in_bytes
) karena konsumsi memori meningkat selama eksekusi. Ini tampaknya terjadi terutama karena rekompilasi (yang harus jelas dengan tampilan usecounts
lapangan 1
)
- yang
BaseSingleStatementPlanKB
bidang harus sesuai dengan CachedPlanSize
atribut dari QueryPlan
node dalam XML, tapi hanya bila menggunakan query satu batch.
- untuk batch dengan beberapa pertanyaan, harus ada baris ditandai sebagai
MEMOBJ_STATEMENT
dalam sys.dm_os_memory_objects
, satu untuk setiap query. The pages_in_bytes
lapangan untuk baris ini harus sesuai dengan individu <QueryPlan>
node dari rencana XML.
Sumber: