Các bảng hệ thống SQL Server có thể được phân mảnh không?


15

Chúng tôi có một số cơ sở dữ liệu trong đó một số lượng lớn các bảng được tạo và loại bỏ. Từ những gì chúng ta có thể nói, SQL Server không tiến hành bảo trì nội bộ trên các bảng cơ sở hệ thống , có nghĩa là chúng có thể trở nên rất phân mảnh theo thời gian và có kích thước lớn. Điều này gây áp lực không cần thiết cho nhóm bộ đệm và cũng tác động tiêu cực đến hiệu suất của các hoạt động như tính toán kích thước của tất cả các bảng trong cơ sở dữ liệu.

Có ai có đề xuất để giảm thiểu phân mảnh trên các bảng nội bộ cốt lõi này không? Một giải pháp rõ ràng có thể tránh việc tạo quá nhiều bảng (hoặc tạo tất cả các bảng tạm thời trong tempdb), nhưng với mục đích của câu hỏi này, hãy nói rằng ứng dụng không có tính linh hoạt đó.

Chỉnh sửa: Nghiên cứu sâu hơn cho thấy câu hỏi chưa được trả lời này , có vẻ liên quan chặt chẽ và chỉ ra rằng một số hình thức bảo trì thủ công thông qua ALTER INDEX...REORGANIZEcó thể là một lựa chọn.


Nghiên cứu ban đầu

Siêu dữ liệu về các bảng này có thể được xem trong 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

Tuy nhiên, sys.dm_db_index_physical_statsdường như không hỗ trợ xem phân mảnh của các bảng này:

-- 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'
)

Các tập lệnh của Ola Hallengren cũng chứa một tham số để xem xét phân mảnh cho is_ms_shipped = 1các đối tượng, nhưng quy trình này âm thầm bỏ qua các bảng cơ sở hệ thống ngay cả khi tham số này được bật. Ola làm rõ rằng đây là hành vi dự kiến; chỉ các bảng người dùng (không phải bảng hệ thống) được ms_shipped (ví dụ msdb.dbo.backupset) được xem xét.

-- 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);


Thông tin yêu cầu bổ sung

Tôi đã sử dụng một điều chỉnh truy vấn của Aaron bên dưới việc sử dụng nhóm bộ đệm của bảng hệ thống kiểm tra và điều này thấy rằng có hàng chục GB bảng hệ thống trong nhóm bộ đệm cho chỉ một cơ sở dữ liệu, trong một số trường hợp, khoảng 80% không gian đó là không gian trống .

-- 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

nhập mô tả hình ảnh ở đây

Câu trả lời:


11

Bạn có chắc chắn rằng bạn đã xác định một cách tích cực và chính xác bảng hệ thống này là nguồn duy nhất của "áp lực không cần thiết đối với vùng đệm và cũng tác động tiêu cực đến hiệu suất của các hoạt động như tính toán kích thước của tất cả các bảng trong cơ sở dữ liệu"? Bạn có chắc rằng bảng hệ thống này không tự quản lý theo cách sao cho (a) phân mảnh được giảm thiểu hoặc giữ bí mật hoặc chỉ (b) quản lý hiệu quả trong bộ nhớ để mức độ phân mảnh thực sự không ảnh hưởng gì nhiều?

Bạn có thể xem có bao nhiêu trang đang được sử dụng, và bạn có thể xem có bao nhiêu không gian miễn phí trên các trang có trong bộ nhớ ( page_free_space_percentluôn luôn là NULLtrong việc phân bổ DMF, nhưng điều này có sẵn từ bộ đệm DMV) - điều này sẽ cung cấp cho bạn một số ý tưởng nếu điều bạn lo lắng thực sự là điều bạn nên lo lắng:

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;

Nếu số lượng trang của bạn nhỏ (có thể là <10000 cho các bảng hệ thống) hoặc nếu không gian trống là "thấp" (không chắc chắn ngưỡng nào điển hình của bạn là để reorg / xây dựng lại), hãy tập trung vào trái cây khác, thú vị hơn, treo thấp hơn .

Nếu số lượng trang của bạn lớn dung lượng trống là "cao", thì có lẽ tôi đang cung cấp cho SQL Server quá nhiều tín dụng để tự bảo trì. Như bạn đã chỉ ra từ câu hỏi khác , điều này hoạt động ...

ALTER INDEX ALL ON sys.syscolpars REORGANIZE;

... và không làm giảm sự phân mảnh. Mặc dù nó có thể yêu cầu quyền nâng cao (tôi đã không thử như một con chim cánh cụt).

Có lẽ bạn chỉ có thể thực hiện việc này định kỳ như một phần của bảo trì của riêng bạn, nếu điều đó làm bạn cảm thấy tốt và / hoặc bạn có bất kỳ bằng chứng nào cho thấy nó có bất kỳ tác động tích cực nào đối với hệ thống của bạn.


Tôi đã thêm một câu trả lời tóm tắt những gì chúng tôi đã làm, và sau đó làm sạch các ý kiến ​​trước đây ở đây. Cảm ơn một lần nữa vì sự giúp đỡ của bạn!
Geoff Patterson

7

Dựa trên hướng dẫn từ câu trả lời của Aaron cũng như nghiên cứu bổ sung, đây là một bài viết nhanh về phương pháp tôi đã thực hiện.

Từ những gì tôi có thể nói, các tùy chọn để kiểm tra sự phân mảnh của các bảng cơ sở hệ thống bị hạn chế. Tôi đã tiếp tục và gửi một vấn đề kết nối để cung cấp khả năng hiển thị tốt hơn, nhưng trong khi đó, có vẻ như các tùy chọn bao gồm những thứ như kiểm tra nhóm bộ đệm hoặc kiểm tra số byte trung bình trên mỗi hàng.

Sau đó tôi đã tạo một thủ tục để thực hiện `ALTER INDEX ... REORGANIZE trên tất cả các bảng cơ sở hệ thống . Thực hiện quy trình này trên một số máy chủ dev được sử dụng nhiều nhất của chúng tôi cho thấy kích thước tích lũy của các bảng cơ sở hệ thống đã được cắt giảm tới 50GB (với ~ 5MM bảng người dùng trên hệ thống, vì vậy rõ ràng là một trường hợp cực đoan).

Một trong những nhiệm vụ bảo trì hàng đêm của chúng tôi, giúp dọn sạch nhiều bảng người dùng được tạo bởi các thử nghiệm và phát triển đơn vị khác nhau, trước đây mất ~ 50 phút để hoàn thành. Một sự kết hợp của sp_whoisactive, sys.dm_os_waiting_tasksDBCC PAGEcho thấy rằng sự chờ đợi bị chi phối bởi I / O trên các bảng cơ sở hệ thống.

Sau khi sắp xếp lại tất cả các bảng cơ sở hệ thống, nhiệm vụ bảo trì giảm xuống ~ 15 phút. Vẫn còn một số chờ đợi I / O, nhưng chúng đã bị giảm đáng kể, có lẽ do một lượng lớn dữ liệu còn lại trong bộ đệm và / hoặc nhiều chi tiết hơn do sự phân mảnh thấp hơn.

Do đó, kết luận của tôi là việc thêm ALTER INDEX...REORGANIZEcác bảng cơ sở hệ thống vào kế hoạch bảo trì có thể là một điều hữu ích để xem xét, nhưng chỉ có thể nếu bạn có một kịch bản trong đó một số lượng đối tượng bất thường đang được tạo trên cơ sở dữ liệu.


+1 cho cả câu hỏi và câu trả lời của bạn - nội bộ là một chút của hộp đen và bạn đã giúp làm sáng tỏ những gì trông giống như một kịch bản thực sự khó chịu cho hiệu suất (ngay cả khi bạn trường hợp cạnh).
Max Vernon
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.