ตารางระบบ SQL Server สามารถจัดระเบียบได้หรือไม่?


15

เรามีฐานข้อมูลหลายแห่งที่สร้างและวางตารางจำนวนมาก จากสิ่งที่เราสามารถบอกได้ 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

ป้อนคำอธิบายรูปภาพที่นี่

คำตอบ:


11

คุณแน่ใจหรือไม่ว่าคุณได้ระบุตารางระบบนี้อย่างถูกต้องและแม่นยำว่าเป็นแหล่งเดียวของ "แรงกดดันที่ไม่จำเป็นในบัฟเฟอร์พูลและยังส่งผลเสียต่อประสิทธิภาพการทำงานเช่นการคำนวณขนาดของตารางทั้งหมดในฐานข้อมูล"? คุณแน่ใจหรือว่าตารางระบบนี้ไม่ได้จัดการด้วยตนเองในลักษณะที่ (a) การกระจายตัวของข้อมูลถูกย่อให้เล็กสุดหรือเก็บไว้ในที่ลับหรือเพียงแค่ (b) จัดการอย่างมีประสิทธิภาพในหน่วยความจำเพื่อให้ระดับการจัดเรียงข้อมูล

คุณสามารถดูได้ว่ามีการใช้งานหน้ากี่หน้าและคุณสามารถดูจำนวนพื้นที่ว่างบนหน้าเว็บที่อยู่ในหน่วยความจำ ( page_free_space_percentอยู่NULLในการจัดสรร DMF เสมอ แต่มีให้จากบัฟเฟอร์ DMV) - สิ่งนี้จะช่วยให้คุณมีความคิด หากสิ่งที่คุณกังวลคือสิ่งที่คุณควรกังวล:

SELECT 
  Number_of_Pages = COUNT(*), 
  Number_of_Pages_In_Memory = COUNT(b.page_id),
  Avg_Free_Space = AVG(b.free_space_in_bytes/8192.0) 
FROM sys.dm_db_database_page_allocations
(
  DB_ID(),
  OBJECT_ID(N'sys.syscolpars'),
  NULL,NULL,'DETAILED'
) AS p
LEFT OUTER JOIN sys.dm_os_buffer_descriptors AS b
ON b.database_id = DB_ID() 
AND b.page_id = p.allocated_page_page_id 
AND b.file_id = p.allocated_page_file_id;

หากจำนวนหน้าของคุณมีขนาดเล็ก (เช่นอาจ <10,000 สำหรับตารางระบบ) หรือถ้าพื้นที่ว่างเป็น "ต่ำ" (ไม่แน่ใจว่าเกณฑ์ปกติของคุณคืออะไรสำหรับการเริ่มใหม่ / สร้างใหม่) ให้มุ่งเน้นที่ผลไม้อื่น ๆ ที่น่าสนใจ .

หากจำนวนหน้าของคุณมีขนาดใหญ่และพื้นที่ว่างเป็น "สูง" โอเคบางทีฉันอาจให้เครดิต SQL Server มากเกินไปสำหรับการบำรุงรักษาด้วยตนเอง ตามที่คุณแสดงให้เห็นจากคำถามอื่น ๆงานนี้ ...

ALTER INDEX ALL ON sys.syscolpars REORGANIZE;

... และไม่ลดการกระจายตัว แม้ว่ามันอาจต้องได้รับการยกระดับสิทธิ์ (ฉันไม่ได้ลองเป็นคน peon)

บางทีคุณอาจทำเช่นนี้เป็นระยะ ๆ เพื่อเป็นส่วนหนึ่งของการบำรุงรักษาของคุณเองถ้ามันทำให้คุณรู้สึกดีและ / หรือคุณมีหลักฐานว่ามีผลกระทบเชิงบวกต่อระบบของคุณเลย


ฉันได้เพิ่มอีกคำตอบสรุปสิ่งที่เราทำลงไปและจากนั้นทำความสะอาดความคิดเห็นก่อนหน้านี้ที่นี่ ขอบคุณอีกครั้งสำหรับความช่วยเหลือของคุณ!
Geoff Patterson

7

จากคำแนะนำจากคำตอบของแอรอนรวมถึงการวิจัยเพิ่มเติมนี่เป็นบทความสั้น ๆ เกี่ยวกับวิธีการที่ฉันทำ

จากสิ่งที่ฉันสามารถบอกได้ตัวเลือกสำหรับการตรวจสอบการกระจายตัวของตารางฐานระบบนั้นมี จำกัด ฉันไปข้างหน้าและยื่นปัญหาการเชื่อมต่อเพื่อให้มองเห็นได้ดีขึ้น แต่ในระหว่างนั้นดูเหมือนว่าตัวเลือกจะรวมถึงสิ่งต่าง ๆ เช่นการตรวจสอบบัฟเฟอร์พูลหรือการตรวจสอบ # เฉลี่ยไบต์ต่อแถว

จากนั้นฉันสร้างโพรซีเดอร์เพื่อดำเนินการ `เปลี่ยนแปลงดัชนี ... จัดวางใหม่บนตารางฐานระบบทั้งหมดจัดระเบียบในทุกตารางฐานระบบ การดำเนินการตามขั้นตอนนี้กับเซิร์ฟเวอร์ dev ที่ใช้บ่อยที่สุด (ab) ของเราแสดงให้เห็นว่าขนาดของตารางฐานระบบที่ถูกตัดมีขนาดสูงสุดถึง 50GB (ด้วยตารางผู้ใช้ ~ 5MM บนระบบดังนั้นจึงเป็นกรณีที่รุนแรงมาก)

หนึ่งในภารกิจการบำรุงรักษายามค่ำคืนของเราซึ่งช่วยทำความสะอาดตารางผู้ใช้จำนวนมากที่สร้างโดยการทดสอบและพัฒนาหน่วยต่างๆก่อนหน้านี้ใช้เวลาประมาณ 50 นาที การรวมกันของsp_whoisactive, sys.dm_os_waiting_tasksและDBCC PAGEแสดงให้เห็นว่าการรอที่ถูกครอบงำโดย I / O บนตารางฐานระบบ

หลังจากการปรับโครงสร้างตารางฐานระบบทั้งหมดงานการบำรุงรักษาลดลงเหลือ ~ 15 นาที ยังคงมี I / O บางส่วนรออยู่ แต่ลดลงอย่างมีนัยสำคัญอาจเป็นเพราะจำนวนข้อมูลที่เหลืออยู่ในแคชและ / หรือ readaheads จำนวนมากขึ้นเนื่องจากการแตกแฟรกเมนต์ที่ต่ำกว่า

ดังนั้นข้อสรุปของฉันคือการเพิ่มALTER INDEX...REORGANIZEตารางฐานระบบลงในแผนการบำรุงรักษาอาจเป็นสิ่งที่มีประโยชน์ในการพิจารณา แต่น่าจะเฉพาะในกรณีที่คุณมีสถานการณ์ที่มีการสร้างวัตถุจำนวนผิดปกติบนฐานข้อมูล


+1 สำหรับทั้งคำถามและคำตอบของคุณ - ภายในเป็นกล่องดำนิดหน่อยและคุณได้ช่วยอธิบายเกี่ยวกับสิ่งที่ดูเหมือนว่าน่ารังเกียจสำหรับประสิทธิภาพการทำงาน (แม้ว่าคุณจะเป็นกรณีขอบ)
Max Vernon
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.