เรามีฐานข้อมูลหลายแห่งที่สร้างและวางตารางจำนวนมาก จากสิ่งที่เราสามารถบอกได้ SQL Server จะไม่ทำการบำรุงรักษาภายในใด ๆ บนตารางฐานของระบบซึ่งหมายความว่าพวกเขาสามารถแยกส่วนกันมากในช่วงเวลาและขนาด bloated สิ่งนี้ทำให้เกิดความกดดันที่ไม่จำเป็นในบัฟเฟอร์พูลและยังส่งผลเสียต่อประสิทธิภาพการทำงานเช่นการคำนวณขนาดของตารางทั้งหมดในฐานข้อมูล
ไม่มีใครมีคำแนะนำสำหรับการลดการกระจายตัวของบนตารางหลักภายในเหล่านี้หรือไม่ วิธีแก้ปัญหาที่ชัดเจนวิธีหนึ่งสามารถหลีกเลี่ยงการสร้างตารางจำนวนมาก (หรือสร้างตารางชั่วคราวทั้งหมดใน tempdb) แต่สำหรับจุดประสงค์ของคำถามนี้สมมติว่าแอปพลิเคชันไม่มีความยืดหยุ่นนั้น
แก้ไข: การวิจัยเพิ่มเติมแสดงคำถามที่ยังไม่ได้ตอบซึ่งมีความเกี่ยวข้องอย่างใกล้ชิดและระบุว่าการบำรุงรักษาด้วยตนเองบางรูปแบบผ่านทางALTER INDEX...REORGANIZE
อาจเป็นตัวเลือก
การวิจัยเบื้องต้น
ข้อมูลเมตาเกี่ยวกับตารางเหล่านี้สามารถดูได้ในsys.dm_db_partition_stats
:
-- The system base table that contains one row for every column in the system
SELECT row_count,
(reserved_page_count * 8 * 1024.0) / row_count AS bytes_per_row,
reserved_page_count/128. AS space_mb
FROM sys.dm_db_partition_stats
WHERE object_id = OBJECT_ID('sys.syscolpars')
AND index_id = 1
-- row_count: 15,600,859
-- bytes_per_row: 278.08
-- space_mb: 4,136
อย่างไรก็ตามsys.dm_db_index_physical_stats
ไม่สนับสนุนการดูการกระจายตัวของตารางเหล่านี้:
-- No fragmentation data is returned by sys.dm_db_index_physical_stats
SELECT *
FROM sys.dm_db_index_physical_stats(
DB_ID(),
OBJECT_ID('sys.syscolpars'),
NULL,
NULL,
'DETAILED'
)
สคริปต์ของ Ola Hallengrenยังมีพารามิเตอร์เพื่อพิจารณาการจัดเรียงข้อมูลสำหรับis_ms_shipped = 1
วัตถุ แต่ขั้นตอนจะละเว้นตารางฐานของระบบอย่างเงียบ ๆ แม้ว่าจะเปิดใช้งานพารามิเตอร์นี้อยู่ก็ตาม โอลาชี้แจงว่านี่เป็นพฤติกรรมที่คาดหวัง; พิจารณาเฉพาะผู้ใช้ตาราง (ไม่ใช่ตารางระบบ) ที่มี ms_shipped (เช่นmsdb.dbo.backupset
)
-- Returns code 0 (successful), but does not do any work for system base tables.
-- Instead of the expected commands to update statistics and reorganize indexes,
-- no commands are generated. The script seems to assume the target tables will
-- appear in sys.tables, but this does not appear to be a valid assumption for
-- system tables like sys.sysrowsets or sys.syscolpars.
DECLARE @result int;
EXEC @result = IndexOptimize @Databases = 'Test',
@FragmentationLow = 'INDEX_REORGANIZE',
@FragmentationMedium = 'INDEX_REORGANIZE',
@FragmentationHigh = 'INDEX_REORGANIZE',
@PageCountLevel = 0,
@UpdateStatistics = 'ALL',
@Indexes = '%Test.sys.sysrowsets.%',
-- Proc works properly if targeting a non-system table instead
--@Indexes = '%Test.dbo.Numbers.%',
@MSShippedObjects = 'Y',
@Execute = 'N';
PRINT(@result);
ข้อมูลที่ร้องขอเพิ่มเติม
ฉันใช้การปรับตัวของแบบสอบถามของ Aaron ด้านล่างการใช้บัฟเฟอร์พูลตารางระบบตรวจสอบและพบว่ามีจำนวนสิบ GB ของตารางระบบในบัฟเฟอร์พูลสำหรับฐานข้อมูลเพียงฐานเดียวโดยประมาณ 80% ของพื้นที่ว่างนั้นเป็นพื้นที่ว่างในบางกรณี .
-- Compute buffer pool usage by system table
SELECT OBJECT_NAME(p.object_id),
COUNT(b.page_id) pages,
SUM(b.free_space_in_bytes/8192.0) free_pages
FROM sys.dm_os_buffer_descriptors b
JOIN sys.allocation_units a
ON a.allocation_unit_id = b.allocation_unit_id
JOIN sys.partitions p
ON p.partition_id = a.container_id
AND p.object_id < 1000 -- A loose proxy for system tables
WHERE b.database_id = DB_ID()
GROUP BY p.object_id
ORDER BY pages DESC