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...REORGANIZE
có 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_stats
dườ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 = 1
cá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