SQL Server sistem tabloları birleştirilebilir mi?


15

Ç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_statsbu 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 = 1nesneler 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

resim açıklamasını buraya girin

Yanıtlar:


11

Bu sistem tablosunu "tampon havuzundaki gereksiz basınç üzerindeki tek kaynak" olarak olumlu ve doğru bir şekilde tanımladığınızdan ve ayrıca bir veritabanındaki tüm tabloların boyutunu hesaplama gibi işlemlerin performansını olumsuz yönde etkilediğinizden emin misiniz? Bu sistem tablosunun, (a) parçalanma en aza indirilecek veya gizlice kontrol altında tutulacak ya da sadece (b) bellekte verimli bir şekilde yönetilecek, böylece birleştirme seviyeleri gerçekten hiçbir şeyi etkilemeyecek şekilde kendi kendine yönetilmediğinden emin misiniz?

Kaç sayfa kullanıldığını görebilirsiniz ve bellekteki sayfalarda ne kadar boş alan olduğunu görebilirsiniz ( page_free_space_percenther zaman NULLDMF ayırmalarında bulunur, ancak bu , arabellek DMV'den kullanılabilir) - bu size biraz fikir vermelidir endişelendiğiniz şey gerçekten endişelenmeniz gereken bir şeyse:

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;

Sayfa sayınız azsa (sistem tabloları için muhtemelen <10000 gibi) veya boş alan "düşük" ise (yeniden düzenleme / yeniden oluşturma için tipik eşiklerinizin ne olduğundan emin değilseniz), diğer, daha ilginç, düşük asılı meyveye odaklanın .

Sayfa sayınız büyükse ve boş alan "yüksek" ise, tamam, belki kendi kendine bakım için SQL Server'a çok fazla kredi veriyorum. Diğer sorudan da görüldüğü gibi , bu işe yarıyor ...

ALTER INDEX ALL ON sys.syscolpars REORGANIZE;

... ve does parçalanması azaltır. Yükseltilmiş izinler gerektirebilmesine rağmen (ben bir peon olarak denemedim).

Belki de, kendinizi iyi hissetmenizi ve / veya sisteminiz üzerinde herhangi bir olumlu etkisi olduğunu gösteren herhangi bir kanıtınız varsa, periyodik olarak kendi bakımınızın bir parçası olarak yapabilirsiniz.


Sonunda ne yaptığımızı özetleyen başka bir cevap ekledim ve daha önce buradaki yorumları temizledim. Yardımın için tekrar teşekkürler!
Geoff Patterson

7

Aaron'un cevabından ve ek araştırmalardan gelen rehberliğe dayanarak, burada aldığım yaklaşımın hızlı bir şekilde yazılması.

Söyleyebileceğim kadarıyla, sistem taban tablolarının parçalanmasını denetleme seçenekleri sınırlıdır. Devam ettim ve daha iyi görünürlük sağlamak için bir Connect sorunu dosyaladım , ancak bu arada seçenekler, arabellek havuzunu incelemek veya satır başına ortalama bayt sayısını kontrol etmek gibi şeyler içeriyor gibi görünüyor.

Sonra bir tüm sistem taban tablolarında `ALTER INDEX ... REORGANIZE işlemini gerçekleştirmek için prosedür . En çok kullanılan (ab) dev sunucularımızdan birkaçında bu prosedürün uygulanması, sistem taban tablolarının kümülatif boyutunun 50 GB'a kadar kesildiğini gösterdi (sistemdeki ~ 5MM kullanıcı tabloları ile, bu yüzden aşırı derecede aşırı bir durum).

Çeşitli birim testleri ve geliştirmeleri tarafından oluşturulan kullanıcı tablolarının çoğunun temizlenmesine yardımcı olan gece bakım görevlerimizden biri, daha önce tamamlanması ~ 50 dakika sürüyordu. Bir kombinasyon sp_whoisactive, sys.dm_os_waiting_tasksveDBCC PAGE bekler sistemi temel tablolar I / O hakim olduğunu göstermiştir.

Tüm sistem taban tablolarının yeniden düzenlenmesinden sonra, bakım görevi ~ 15 dakikaya düştü. Hala bazı G / Ç beklemeleri vardı, ancak belki de önbellekte daha fazla miktarda veri ve / veya daha düşük parçalanma nedeniyle daha fazla okuma kafası nedeniyle önemli ölçüde azaldılar.

Bu nedenle, sonuçum, ALTER INDEX...REORGANIZEbir bakım planına sistem taban tabloları eklemenin yararlı bir şey olabileceğidir, ancak muhtemelen yalnızca bir veritabanında olağandışı sayıda nesnenin oluşturulduğu bir senaryo varsa.


Sorunuzun ve cevap her ikisi için 1 - internals bir kara kutudan biraz vardır ve performans için gerçekten kötü senaryo (sizin bile nasıl göründüğünü biraz ışık tutacak yardımcı olduk olan bir kenar durum).
Max Vernon
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.