Le tabelle di sistema di SQL Server possono essere deframmentate?


15

Abbiamo diversi database in cui vengono creati e rilasciati un gran numero di tabelle. Da quello che possiamo dire, SQL Server non esegue alcuna manutenzione interna sulle tabelle di base del sistema , il che significa che possono diventare molto frammentati nel tempo e gonfiati di dimensioni. Ciò esercita una pressione non necessaria sul pool di buffer e influisce negativamente anche sulle prestazioni di operazioni come il calcolo delle dimensioni di tutte le tabelle in un database.

Qualcuno ha suggerimenti per ridurre al minimo la frammentazione su queste tabelle interne core? Una soluzione ovvia potrebbe evitare di creare così tante tabelle (o creare tutte le tabelle temporanee in tempdb), ma ai fini di questa domanda diciamo che l'applicazione non ha quella flessibilità.

Modifica: ulteriori ricerche mostrano questa domanda senza risposta , che sembra strettamente correlata e indica che una qualche forma di manutenzione manuale tramite ALTER INDEX...REORGANIZEpotrebbe essere un'opzione.


Ricerca iniziale

I metadati su queste tabelle possono essere visualizzati in 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

Tuttavia, sys.dm_db_index_physical_statsnon sembra supportare la visualizzazione della frammentazione di queste tabelle:

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

Gli script di Ola Hallengren contengono anche un parametro per considerare la deframmentazione per gli is_ms_shipped = 1oggetti, ma la procedura ignora silenziosamente le tabelle di base del sistema anche con questo parametro abilitato. Ola ha chiarito che questo è il comportamento previsto; vengono prese in msdb.dbo.backupsetconsiderazione solo le tabelle utente (non le tabelle di sistema) che sono ms_shipped (ad esempio ).

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


Ulteriori informazioni richieste

Ho usato un adattamento della query di Aaron al di sotto dell'utilizzo del pool buffer della tabella di sistema inspect e questo ha rilevato che ci sono decine di GB di tabelle di sistema nel pool buffer per un solo database, con ~ 80% di quello spazio che è spazio libero in alcuni casi .

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

inserisci qui la descrizione dell'immagine

Risposte:


11

Sei sicuro di aver identificato in modo positivo e accurato questa tabella di sistema come l'unica fonte di "pressione non necessaria sul pool di buffer e influendo negativamente anche sulle prestazioni di operazioni come calcolare la dimensione di tutte le tabelle in un database"? Sei sicuro che questa tabella di sistema non sia autogestita in modo tale che (a) la frammentazione sia minimizzata o tenuta sotto controllo in segreto o semplicemente (b) gestita in modo efficiente nella memoria in modo che i livelli di deframmentazione non influiscano davvero molto?

Puoi vedere quante pagine sono in uso e puoi vedere quanto spazio libero c'è nelle pagine che sono in memoria ( page_free_space_percentè sempre NULLnelle allocazioni DMF, ma questo è disponibile dal buffer DMV) - questo dovrebbe darti un'idea se ciò di cui ti preoccupi è davvero qualcosa di cui dovresti preoccuparti:

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;

Se il tuo numero di pagine è piccolo (come probabilmente <10000 per le tabelle di sistema) o se lo spazio libero è "basso" (non sei sicuro di quali siano le tue soglie tipiche per riporgere / ricostruire), concentrati su altri frutti più interessanti e con un basso appeso .

Se il tuo numero di pagine è grande e lo spazio libero è "alto", ok, forse sto dando troppo credito a SQL Server per la sua auto-manutenzione. Come hai mostrato dall'altra domanda , questo funziona ...

ALTER INDEX ALL ON sys.syscolpars REORGANIZE;

... e lo fa ridurre la frammentazione. Sebbene possa richiedere autorizzazioni elevate (non ho provato come peon).

Forse puoi semplicemente farlo periodicamente come parte della tua manutenzione, se ti fa sentire bene e / o hai qualche prova che abbia alcun impatto positivo sul tuo sistema.


Ho aggiunto un'altra risposta che riassume ciò che abbiamo finito per fare, quindi ho ripulito i commenti precedenti qui. Grazie ancora per il vostro aiuto!
Geoff Patterson,

7

Sulla base della guida fornita dalla risposta di Aaron e di ulteriori ricerche, ecco un rapido resoconto dell'approccio che ho seguito.

Da quello che posso dire, le opzioni per l'ispezione della frammentazione delle tabelle di base del sistema sono limitate. Sono andato avanti e ho presentato un problema di Connect per fornire una migliore visibilità, ma nel frattempo sembra che le opzioni includano cose come esaminare il pool di buffer o controllare il numero medio di byte per riga.

Ho quindi creato una procedura per eseguire `ALTER INDEX ... RIORGANIZE su tutte le tabelle di base del sistema . L'esecuzione di questa procedura su alcuni dei nostri server di sviluppo più utilizzati (ab) ha mostrato che le dimensioni cumulative delle tabelle di base del sistema sono state ridotte fino a 50 GB (con tabelle utente di ~ 5 MM sul sistema, quindi chiaramente un caso estremo).

Una delle nostre attività di manutenzione notturna, che aiuta a ripulire molte delle tabelle utente create da vari test unitari e sviluppo, in precedenza richiedeva circa 50 minuti per essere completata. Una combinazione di sp_whoisactive, sys.dm_os_waiting_taskse ha DBCC PAGEmostrato che le attese erano dominate dall'I / O sulle tabelle di base del sistema.

Dopo la riorganizzazione di tutte le tabelle di base del sistema, l'attività di manutenzione è scesa a ~ 15 minuti. C'erano ancora alcune attese di I / O, ma erano significativamente diminuite, forse a causa di una maggiore quantità di dati rimanenti nella cache e / o più readahead a causa della frammentazione ridotta.

Pertanto, la mia conclusione è che l'aggiunta ALTER INDEX...REORGANIZEdi tabelle di base del sistema in un piano di manutenzione può essere una cosa utile da considerare, ma probabilmente solo se si dispone di uno scenario in cui un numero insolito di oggetti viene creato su un database.


+1 sia per la tua domanda che per la risposta: gli interni sono un po 'una scatola nera e hai contribuito a far luce su quello che sembra uno scenario davvero brutto per le prestazioni (anche se il tuo è un caso limite).
Max Vernon,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.