Çok sayıda tablonun oluşturulduğu ve bırakıldığı birkaç veritabanımız var. Söyleyebileceğimizden, SQL Server sistem taban tablolarında herhangi bir dahili bakım yapmaz , bu da zamanla çok parçalanmış ve boyut olarak şişirilebileceği anlamına gelir. Bu, arabellek havuzuna gereksiz baskı uygular ve ayrıca bir veritabanındaki tüm tabloların boyutunu hesaplama gibi işlemlerin performansını olumsuz etkiler.
Herkes bu çekirdek iç tablolarda parçalanma en aza indirmek için öneriler var mı? Açık bir çözüm, çok fazla tablo oluşturmaktan (veya tempdb'de tüm geçici tabloları oluşturmaktan) kaçınmak olabilir, ancak bu sorunun amacı için uygulamanın bu esnekliğe sahip olmadığını varsayalım.
Düzenleme: Daha fazla araştırma, yakından ilişkili olan ve aracılığıyla manuel bakımın bir biçiminin bir seçenek olabileceğini gösteren bu cevaplanmamış soruyu göstermektedir ALTER INDEX...REORGANIZE
.
İlk araştırma
Bu tablolarla ilgili meta veriler şurada görüntülenebilir 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
Ancak, sys.dm_db_index_physical_stats
bu tabloların parçalara ayrılmasını görüntülemeyi desteklemiyor gibi görünüyor:
-- 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'in komut dosyaları , is_ms_shipped = 1
nesneler için birleştirmeyi düşünmek için bir parametre içerir , ancak yordam bu parametre etkinken bile sistem taban tablolarını sessizce yok sayar. Ola bunun beklenen davranış olduğunu açıkladı; yalnızca ms_shipped (örn. msdb.dbo.backupset
) olan kullanıcı tabloları (sistem tabloları değil ) dikkate alınır.
-- 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);
İstenen ek bilgiler
Aaron'un sorgusunu sistem tablosu arabellek havuzu kullanımının altında bir uyarlama kullandım ve bu, yalnızca bir veritabanı için arabellek havuzunda onlarca GB sistem tablosu bulunduğunu, bazı durumlarda bu alanın ~% 80'inin boş alan olduğunu buldu. .
-- 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