it-swarm.it

Perché il mio database è ancora frammentato dopo aver ricostruito e reindicizzato tutto?

Ho un database che ho provato a deframmentare tutte le tabelle contemporaneamente eseguendo questo T-SQL:

SELECT 
        'ALTER INDEX all ON ' + name + ' REORGANIZE;' + CHAR(10) +
        'ALTER INDEX all ON ' + name + ' REBUILD;'
    FROM sys.tables

E quindi copiare e incollare l'output in una nuova finestra di query ed eseguirlo. Non ho riscontrato errori, ma ho ancora frammentazione. Ho provato a eseguire entrambi i comandi separatamente e ho ancora frammentazione. Nota: Sono stato reso consapevole che REORGANIZE non è necessario da Aaron e sono consapevole che potrei usare sql dinamico per automatizzare questo.

Ho eseguito questo per determinare che ho ancora la frammentazione:

SELECT * FROM 
sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, NULL) 
WHERE avg_fragmentation_in_percent > 0

E ho ottenuto:

database_id object_id   index_id    partition_number    index_type_desc alloc_unit_type_desc    index_depth index_level avg_fragmentation_in_percent    fragment_count  avg_fragment_size_in_pages  page_count  avg_page_space_used_in_percent  record_count    ghost_record_count  version_ghost_record_count  min_record_size_in_bytes    max_record_size_in_bytes    avg_record_size_in_bytes    forwarded_record_count  compressed_page_count
85  171147655   1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   36.3636363636364    5   2.2 11  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  421576540   1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   75  7   1.14285714285714    8   NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  965578478   1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   14.7058823529412    6   5.66666666666667    34  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  1061578820  1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   40  4   1.25    5   NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  1109578991  1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   30.7692307692308    5   2.6 13  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  1205579333  2   1   NONCLUSTERED INDEX  IN_ROW_DATA 2   0   50  5   1.6 8   NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  1493580359  1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   50  6   1.66666666666667    10  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL

So che mi manca qualcosa di veramente semplice, ma non so cosa.

41
Justin Dearing

I tavoli sono piccoli. I conteggi delle pagine nelle tue tabelle sono:

11, 8, 6, 5, 13, 8, 10

Occupano 480kb in totale. Non c'è letteralmente nulla da deframmentare.

Modifica: questo merita una spiegazione in più.

A una nuova tabella o indice vengono generalmente assegnate le prime 8 pagine da una dimensione mista, piuttosto che uniforme. Pertanto, è possibile assegnare ciascuna delle prime 8 pagine da diverse estensioni miste. Una tabella o un indice che consuma 8 pagine potrebbe quindi avere 8 frammenti, 1 su ciascuna delle 8 diverse estensioni miste.

Gli script di deframmentazione più utilizzati (un paio di esempi collegati di seguito) tendono ad escludere piccole tabelle per questo motivo. IIRC, <500 pagine sono in una o entrambe. A queste dimensioni, la deframmentazione presenta pochi benefici e le cifre della frammentazione sono potenzialmente distorte dalle allocazioni di entità mista.

38

Citazione da " Best practice per la deframmentazione dell'indice di Microsoft SQL Server 20 ":

"La frammentazione influisce sull'I/O del disco. Pertanto, concentrati sugli indici più grandi perché le loro pagine hanno meno probabilità di essere memorizzate nella cache da SQL Server. Usa il conteggio delle pagine riportato da DBCC SHOWCONTIG per avere un'idea delle dimensioni degli indici (ogni pagina è 8 KB di dimensione). In generale, non dovresti preoccuparti dei livelli di frammentazione degli indici con meno di 1.000 pagine. Nei test, gli indici che contengono più di 10.000 pagine hanno realizzato miglioramenti delle prestazioni, con il più grande guadagni su indici con significativamente più pagine (maggiore di 50.000 pagine) . "

Quindi questo tipo di risposte alla tua domanda e supporta le risposte di Mark e Aaron.

Puoi trovare buone informazioni sulla frammentazione dell'indice nei seguenti articoli di Brent Ozar:

Inoltre..un oceano di grandi informazioni sugli indici in generale (anche sui problemi di frammentazione) è disponibile sul blog di Kimberly Tripp .

20
Marian

Questo non ha lo scopo di rispondere alla tua domanda, ma non entrerà mai in un commento. Puoi creare questo script in modo dinamico senza dover copiare e incollare l'output in un'altra finestra. Tenendo conto del fatto che non esiste assolutamente alcun motivo per REORGANIZE e quindi REBUILD:

DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql += N'ALTER INDEX all ON ' + name + ' REBUILD;
    ' FROM sys.tables;

PRINT @sql; -- to see the first 8,000 characters and make sure it checks out
-- EXEC sp_executesql @sql;
12
Aaron Bertrand