Rencanakan ukuran cache dan memori yang dicadangkan

18

Saat menjalankan kueri termasuk Rencana Eksekusi Aktual, operator root ( SELECT) memberi tahu saya bahwa Ukuran Cached Plan adalah 32KB.

Kueri yang bergabung sys.dm_exec_cached_plansdan sys.dm_os_memory_objects, melihat paket yang dimaksud, mengatakan bahwa nilai untuk pages_in_bytesdan max_pages_in_bytes32768 (32KB), yang cocok dengan ukuran paket yang di-cache.

Apa yang saya tidak mengerti adalah apa nilainya sys.dm_exec_cached_plans.size_in_bytes, yaitu 49152 (48KB). Saya telah membaca BOL di semua kolom ini, dan terutama size_in_bytesyang mengatakan:

" Jumlah byte yang dikonsumsi oleh objek cache. "

Saya tidak bisa mendapatkan potongan puzzle terakhir di tempat, untuk memahami apa artinya sebenarnya.

Saya tahu bahwa semua operator (tidak berbicara tentang hibah memori tambahan yang digunakan untuk pengurutan dan hash) memerlukan sejumlah memori tetap, untuk menyimpan keadaan, membuat perhitungan, dll., Yang disimpan dengan paket yang dioptimalkan dalam cache, tetapi di mana?

Jadi, pertanyaan saya adalah:

  • Apa yang size_in_bytesbenar-benar berarti
  • Mengapa nilai ini lebih tinggi dari "Ukuran paket cache"?
  • Di mana jumlah memori tetap untuk semua operator / iterator dicadangkan, apakah dengan "Cached plan size" (32Kb dalam contoh saya), atau di tempat lain?

Saya tahu mereka DMV yang berbeda dengan fungsi yang berbeda, tetapi mereka terkait. Paket yang dikompilasi (di-cache) sys.dm_exec_cached_plansbergabung sys.dm_os_memory_objectsdalam memory_object_addresskolom. Alasan saya memposting pertanyaan di sini, adalah bahwa saya meminta bantuan tentang ini, memahami bagaimana menafsirkan DMV dan kolom mereka.

Jika size_in_bytesukuran paket di-cache, mengapa SQL Server mengatakan nilai lain dalam rencana eksekusi aktual?

Kueri baru, nomor baru:

  • Rencana aktual
    • Cached Plan Ukuran 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.

Juga, perhatikan bahwa permintaan ini tidak memerlukan hibah memori tambahan untuk operasi sort dan hash.

Microsoft SQL Server 2012 - 11.0.5343.0 (X64)
GordonLiddy
sumber

Jawaban:

12

Alasan bahwa size_in_bytesbidang sys.dm_exec_cached_plansDMV, setidaknya dalam hal "Paket yang Dikompilasi", lebih besar dari CachedPlanSizeatribut QueryPlansimpul 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_bytesbidang. 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_objectsyang ditautkan melalui memory_object_addressbidang 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_objectsDMF. 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_bytesnilai untuk objek utama dibagi 1024 harus cocok dengan CachedPlanSizeukuran di <QueryPlan>simpul rencana XML. Nilai-nilai itu tidak akan menyamakan, dalam batch multi-pernyataan.


The size_in_bytesnilai dapat diturunkan dengan menjumlahkan entri di sys.dm_os_memory_objectsDMV (item disebutkan di atas dalam huruf tebal), semua yang berhubungan dengan dm_os_memory_objects.page_allocator_addressuntuk itu Disusun Rencana. Trik untuk mendapatkan nilai yang benar adalah dengan terlebih dahulu mendapatkan memory_object_addressdari sys.dm_exec_cached_plansuntuk Paket Kompilasi tertentu, kemudian menggunakannya untuk mendapatkan baris MEMOBJ_COMPILE_ADHOC yang sesuai dari sys.dm_os_memory_objectsberdasarkan memory_object_addressbidangnya. Lalu, ambil page_allocator_addressnilai dari sys.dm_os_memory_objectsuntuk baris itu, dan gunakan untuk mengambil semua baris dari sys.dm_os_memory_objectsyang 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_addressnilai 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_plansbersama dengan Rencana Kueri dan pernyataan untuk setiap kumpulan. Kueri langsung di atas dimasukkan ke dalam kueri di bawah ini melalui XML sebagai MemoryObjectsbidang:

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 TotalPlanBytesbidang hanya re-pernyataan dari sys.dm_exec_cached_plans.size_in_byteslapangan,
  • yang AllocatedBytesbidang adalah SUM dari obyek memori terkait yang biasanya cocok TotalPlanBytes(yaitu size_in_bytes)
  • yang AllocatedByteslapangan 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 usecountslapangan 1)
  • yang BaseSingleStatementPlanKBbidang harus sesuai dengan CachedPlanSizeatribut dari QueryPlannode dalam XML, tapi hanya bila menggunakan query satu batch.
  • untuk batch dengan beberapa pertanyaan, harus ada baris ditandai sebagai MEMOBJ_STATEMENTdalam sys.dm_os_memory_objects, satu untuk setiap query. The pages_in_byteslapangan untuk baris ini harus sesuai dengan individu <QueryPlan>node dari rencana XML.

Sumber:

Solomon Rutzky
sumber