ricostruita su indice cluster, perché il ridimensionamento dei dati si riduce?


10

Quando abbiamo fatto una ricostruzione su un indice cluster su una tabella che contiene circa 15 GB di dati e il formato dei dati si è ridotto a 5 GB, come può essere? Che tipo di "dati" viene rimosso?

Dimensione dei dati intendo la colonna "dati" di DBCC sp_spaceused

Prima di ricostruire su indice cluster:

name                  rows        reserved    data        index_size  unused
LEDGERJOURNALTRANS    43583730    39169656 KB 15857960 KB 22916496 KB 395200 KB

Dopo la ricostruzione su indice cluster:

name                  rows        reserved    data        index_size  unused
LEDGERJOURNALTRANS    43583730    29076736 KB 5867048 KB  22880144 KB 329544 KB

TSQL per la ricostruzione:

USE [DAX5TEST]
GO
ALTER INDEX [I_212RECID] ON [dbo].[LEDGERJOURNALTRANS] REBUILD PARTITION = ALL WITH ( PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON, ONLINE = ON, SORT_IN_TEMPDB = OFF, DATA_COMPRESSION = PAGE, FILLFACTOR = 85 )
GO

Stai determinando la dimensione dei dati dalla dimensione del file?
JNK,

Dimensione dei dati intendo la colonna "dati" di DBCC sp_spaceused
Daniel Björk,

Questa sarebbe la colonna "dati" di EXEC sp_spaceused.
RLF,

1
Ogni corpo ha mancato che OP utilizza la compressione della pagina = abilitato nel suo script di ricostruzione e immagino che non lo fosse prima. Daniel puoi confermare?
Shanky,

1
@Grazie: ALTER INDEXSembra che sia stata generata dal codice (in quanto include un sacco di opzioni nelle loro impostazioni predefinite) quindi sospetto che sia stata creata dalle opzioni esistenti dell'indice. Ma hai ragione: se la compressione non fosse abilitata sull'indice cluster prima dell'esecuzione, ciò spiegherebbe sicuramente la maggior parte della riduzione dell'impronta dei dati. (di nuovo: Daniel, potresti confermare in un modo o nell'altro?)
David Spillett,

Risposte:


16

Quando una tabella ha un indice cluster, l'indice è i dati della tabella (altrimenti si dispone di una tabella dei tipi di heap). Una ricostruzione dell'indice cluster (qualsiasi indice in effetti, ma lo spazio non verrebbe conteggiato come "dati" per un indice non cluster) comporterà l'unione delle pagine parzialmente utilizzate in una forma più completa.

Man mano che si inseriscono i dati in un indice (raggruppato o meno) nelle pagine foglia dell'ordine dell'indice vengono create secondo necessità e si avrà sempre e solo una pagina parziale: quella alla fine. Quando inserisci i dati fuori dall'ordine dell'indice, una pagina deve essere divisa affinché i dati si adattino al posto giusto: finisci con due pagine che sono piene per circa la metà e la nuova riga va in una di esse. Nel tempo ciò può accadere molto, consumando una buona quantità di spazio extra, sebbene in futuro gli inserti colmeranno alcune lacune. Anche le pagine non foglia vedranno un effetto simile, ma le pagine di dati reali hanno dimensioni molto più significative di quanto non siano.

Inoltre, le eliminazioni possono causare pagine parziali. Se si rimuovono tutte le righe in una pagina, vengono conteggiate come "non utilizzate", ma se sono rimaste una o più righe di dati, vengono comunque conteggiate come in uso. Anche se esiste una sola riga che utilizza 10 byte in una pagina, quella pagina conta come 8192 byte nel conteggio dello spazio utilizzato. Anche in questo caso inserti futuri potrebbero colmare parte del gap.

Per le righe di lunghezza variabile, anche gli aggiornamenti possono avere lo stesso effetto: man mano che una riga si restringe, può lasciare spazio nella sua pagina che non è successivamente facile da riutilizzare e se una riga in una pagina quasi intera si allunga, potrebbe forzare una divisione della pagina .

SQL Server non passa il tempo a cercare di normalizzare i dati riorganizzando il modo in cui le pagine vengono utilizzate, fino a quando non viene esplicitamente comunicato a come l'ordine di ricostruzione dell'indice, poiché tali esercizi di garbage collection potrebbero essere un incubo di prestazioni.

Sospetto che questo sia ciò che stai vedendo, anche se direi che avere uno spazio sufficiente allocato per ~ 2,7 volte la quantità di dati assolutamente necessaria è un caso particolarmente negativo. Potrebbe implicare che tu abbia qualcosa di casuale come una delle chiavi significative nell'indice (forse una colonna UUID), il che significa che è improbabile che nuove righe vengano mai aggiunte nell'ordine dell'indice e / o che un numero significativo di eliminazioni si sia verificato di recente.

Esempio di suddivisione della pagina

Inserimento in ordine di indice con righe a lunghezza fissa di cui quattro si adattano a una pagina:

Start with one empty page: 
        [__|__|__|__]
Add the first item in index order:
        [00|__|__|__]
Add the next three
        [00|02|04|06]
Adding the next will result in a new page:
        [00|02|04|06] [08|__|__|__]
And so on...
        [00|02|04|06] [08|10|12|14] [16|18|__|__]

Ora per aggiungere righe fuori dall'ordine dell'indice (ecco perché ho usato numeri pari solo sopra): aggiungere 11significherebbe estendere quella seconda pagina (non possibile in quanto sono di dimensioni fisse), spostando tutto sopra 11 su uno (decisamente troppo costoso su un indice di grandi dimensioni) o suddividere la pagina in questo modo:

[00|02|04|06] [08|10|11|__] [12|14|__|__] [16|18|__|__]

Da qui, l'aggiunta 13e 17non si tradurrà in una divisione in quanto vi è attualmente spazio nelle pagine pertinenti:

[00|02|04|06] [08|10|11|__] [12|13|14|__] [16|17|18|__]

ma aggiungendo 03 sarà:

[00|02|03|__] [04|06|__|__] [08|10|11|__] [12|13|14|__] [16|17|18|__]

Come puoi vedere, dopo quelle operazioni di inserimento al momento abbiamo allocato 5 pagine di dati che potrebbero contenere un totale di 20 righe, ma abbiamo solo 14 righe lì ("sprecando" il 30% dello spazio).

Una ricostruzione con opzioni predefinite (vedi sotto "fattore di riempimento") comporterebbe:

[00|02|03|04] [06|08|10|11] [12|13|14|16] [17|18|__|__]

salvare una pagina in questo semplice esempio. È facile vedere come le eliminazioni possono avere un effetto simile agli inserti fuori dall'indice.

attenuazione

Se ci si aspetta che i dati arrivino in un ordine abbastanza casuale rispetto all'ordine dell'indice, è possibile utilizzare l' FILLFACTORopzione durante la creazione o la ricostruzione di un indice per dire a SQL Server di lasciare artificialmente vuoti da riempire in seguito, riducendo le divisioni di pagina a lungo termine ma prendendo più spazio inizialmente. Naturalmente sbagliare questo valore può peggiorare le cose piuttosto che migliorare la situazione, quindi gestisci con cura.

La suddivisione della pagina, in particolare sull'indice cluster, può avere un impatto sulle prestazioni per inserimenti / aggiornamenti, pertanto a FILLFACTORvolte è ottimizzata per quel motivo invece del problema di utilizzo dello spazio nei database che vedono molte attività di scrittura (ma per la maggior parte delle app, dove le letture superano le scritture per diversi ordini di grandezza, è generalmente meglio lasciare il fattore di riempimento al 100%, tranne per casi specifici come quelli in cui si hanno indici su colonne con contenuti effettivamente casuali).

Presumo che altri DB di grandi nomi abbiano un'opzione simile, se hai bisogno anche di questo livello di controllo.

Aggiornare

Per quanto riguarda l' ALTER INDEXaffermazione aggiunta alla domanda dopo che ho iniziato a digitare quanto sopra: suppongo che le opzioni siano le stesse di quando l'indice è stato creato (o ricostruito per ultimo) ma in caso contrario l'opzione di compressione potrebbe essere molto significativa se fosse stata aggiunta questa tempo intorno. Anche in questa affermazione il fillfactor è impostato su 85% non 100%, quindi ogni pagina foglia sarà ~ 15% vuota immediatamente dopo la ricostruzione.


2
+1 Se il fattore di riempimento della pagina è inferiore al 100%, ad esempio se il fattore di riempimento della pagina era del 50%, l'indice cluster ricostruito di recente (la tabella ) sarebbe due volte più grande di se fosse ricostruito con un fattore di riempimento del 100%.
Max Vernon,

6

Quando si ricostruisce un indice, posiziona letteralmente tutti i dati in nuove pagine. Ciò che sospetto sia successo è che hai rimosso molti dati prima della ricostruzione, ad esempio rimosso una colonna, aggiornato una colonna a larghezza variabile per avere meno dati, modificato una dimensione della colonna a larghezza fissa o eliminato molte righe. Entrambe queste operazioni potrebbero lasciare molto spazio vuoto sulle pagine, che non verrebbero recuperate fino alla ricostruzione. La colonna "dati" sp_spaceusednon sta misurando i dati effettivi, ma il numero di pagine 8K utilizzate per archiviare i dati. Quelle pagine sono ora più piene a causa della ricostruzione, quindi la stessa quantità di dati si adatta a un numero inferiore di pagine.


5

La sp_spaceusedprocedura memorizzata non esamina la dimensione totale cumulativa delle righe nel database. Riporta la dimensione dello spazio allocato per contenere tali dati nella dimensione cumulativa delle estensioni allocate per i dati.

Se è disponibile uno spazio libero significativo, ad esempio da molte righe eliminate, una ricostruzione dell'indice cluster compattare lo spazio in pagine ed estensioni per essere più efficiente (ovvero più piccolo) per motivi di prestazioni.

Pertanto, nessun dato avrebbe dovuto essere scartato, ma il processo di ricostruzione ha reso di nuovo disponibile lo spazio libero incorporato nelle pagine di dati.

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.