Quali sono gli scenari di utilizzo validi per le tabelle HEAP?


31

Attualmente sto effettuando alcune importazioni di dati in un sistema legacy e ho scoperto che questo sistema non utilizza un singolo indice cluster. Una rapida ricerca su Google mi ha fatto conoscere il concetto di tabelle HEAP e ora sono curioso di sapere quali scenari di utilizzo una tabella HEAP dovrebbe essere preferita rispetto a una tabella cluster?

Per quanto ho capito, una tabella HEAP sarebbe utile solo per le tabelle di controllo e / o in cui gli inserimenti avvengono molto più spesso di quanto selezioni. Consentirebbe di risparmiare spazio su disco e I / O su disco poiché non esiste un indice cluster da mantenere e la frammentazione aggiuntiva non sarebbe un problema a causa delle letture molto rare.


1
Stai parlando di SQL Server?
a_horse_with_no_name

@a_horse_with_no_name sì, ho dimenticato di menzionare che sry
marc.d

Le tabelle heap sono utili per le tabelle con milioni di righe colpite pesantemente dagli utenti. Il rovescio della medaglia è che possono occupare molto spazio perché i dati sono archiviati fisicamente non ordinati. Inoltre, fai affidamento sugli indici per essere sintonizzato sulle tue query. Ho lavorato in luoghi che non utilizzavano affatto gli indici cluster a causa di problemi di prestazioni. Probabilmente a causa di scarse scelte di indice cluster, ma se usi solo le tabelle heap non devi preoccuparti. Una soluzione migliore sarebbe quella di utilizzare l'edizione enterprise del server sql e partizionare orizzontalmente la tabella di grandi dimensioni. Ma se non hai l'ent


Risposte:


22

Gli unici usi validi sono per

  • tabelle di gestione temporanea utilizzate nei processi di importazione / esportazione / ETL.
  • backup ad hoc, temporaneo ea breve termine delle tabelle mediante SELECT * INTO..

Le tabelle di gestione temporanea sono in genere piuttosto piatte e troncate prima / dopo l'uso.

Si noti che un indice cluster è in genere di dimensioni ridotte rispetto alla dimensione dei dati: i dati rappresentano il livello più basso della struttura dell'indice.

Anche le tabelle di heap hanno problemi. Almeno questi:

Vedi anche


2
In genere utilizza heap per due cose separate. Tabelle di gestione temporanea e di lavoro ETL che utilizzo per archiviare temporaneamente i dati quando il set è troppo grande affinché una tabella temporanea funzioni in modo efficace. Tutto ciò viene troncato al successivo caricamento.
Zane,

Buona domanda a proposito.
Zane,

1
Una leggera modifica: se si esegue SELECT INTO per creare un backup rapido di una piccola tabella prima di apportare una modifica, per impostazione predefinita viene creato un heap. Direi che è un uso valido, ma è solo un pignolo. Vorrei liberarmi di quel mucchio non appena sapessi che il mio lavoro era finito.
Brent Ozar,

@BrentOzar: D'accordo, lo faccio sempre. Lo spirito della mia risposta è "tabelle a lungo termine e persistenti", ma aggiornerò
gbn

9

Principali considerazioni

Vedo un vantaggio importante per gli heap e uno per le tabelle raggruppate, oltre a una terza considerazione che può andare in entrambi i modi.

  • Un heap ti consente di risparmiare un livello di riferimento indiretto. Gli indici contengono ID di riga, che puntano direttamente (bene, non proprio, ma il più direttamente possibile) a una posizione del disco. Pertanto, una ricerca di indice contro un heap dovrebbe costare all'incirca la metà di una ricerca di indice non cluster contro una tabella di cluster.

  • Un indice cluster viene ordinato, di per sé, grazie a un indice (quasi) libero. Poiché l'indice di clustering si riflette nell'ordine fisico dei dati, occupa relativamente poco spazio sopra i dati effettivi stessi, che ovviamente è necessario archiviare comunque. Poiché è fisicamente ordinato, una scansione dell'intervallo rispetto a questo indice può cercare il punto iniziale e quindi comprimere in modo molto efficiente il punto finale.

  • Gli indici sui cumuli di riferimento di heap, che sono 64 bit. Come accennato, gli indici non cluster su una tabella cluster fanno riferimento alla chiave di clustering, che può essere più piccola (un 32 bit INT), uguale (un 64 bit BIGINT) o più grande (un 48 bit DATETIME2()più un 32 bit INT, o un GUID a 128 bit). Ovviamente un riferimento più ampio rende indici più grandi e più costosi.

Requisiti di spazio

Con queste due tabelle:

CREATE TABLE TmpClustered
(
ID1 INT NOT NULL,
ID2 INT NOT NULL
)
ALTER TABLE TmpClustered ADD CONSTRAINT PK_Tmp1 PRIMARY KEY CLUSTERED (ID1)
CREATE UNIQUE INDEX UQ_Tmp1 ON TmpClustered (ID2)

CREATE TABLE TmpNonClustered
(
ID1 INT NOT NULL,
ID2 INT NOT NULL
)
ALTER TABLE TmpNonClustered ADD CONSTRAINT PK_Tmp2 PRIMARY KEY NONCLUSTERED (ID1)
CREATE UNIQUE INDEX UQ_Tmp2 ON TmpNonClustered (ID2)

... ciascuno popolato con 8,7 M di record, lo spazio richiesto era di 150 MB per i dati per entrambi; 120 MB per gli indici della tabella cluster, 310 MB per gli indici della tabella non cluster. Ciò riflette che l'indice cluster è più stretto di un RID e che l'indice cluster è principalmente un "omaggio". Senza gli indici univoci attivi ID2, lo spazio dell'indice richiesto scende a 155 MB per la tabella non cluster (metà, come ci si aspetterebbe), ma solo 150 KB per il PK cluster: quasi nulla.

Quindi un indice non cluster di un campo a 32 bit in una tabella cluster con un indice a 32 bit (totale 64 bit, nominalmente) ha richiesto 120 MB, mentre un indice di un campo a 32 bit in un heap con 64 bit Il RID (in totale 96 bit, nominalmente) ha richiesto 155 MB, un po 'meno dell'aumento del 50% che ci si aspetterebbe ingenuamente di passare da 64 a 96 bit, ma ovviamente c'è un overhead che riduce l'effettiva differenza di dimensioni.

Il popolamento delle due tabelle e la creazione dei loro indici ha richiesto lo stesso tempo per ciascuna tabella. Eseguendo semplici test che coinvolgono scansioni o ricerche, non ho trovato differenze sostanziali di prestazioni tra le tabelle, che corrispondono al white paper di Microsoft che gbn ha collegato utile. Detto documento mostra una differenza significativa per l'accesso altamente concorrenziale; Non sono sicuro del perché ciò accada, si spera che qualcuno con più esperienza di me con sistemi OLTP ad alto volume possa dircelo.

L'aggiunta di ~ 40 byte di dati casuali di lunghezza variabile non ha modificato sensibilmente questa equivalenza. Nemmeno la sostituzione della INTs con UUID ampi (ogni tabella è stata rallentata all'incirca nella stessa misura). La vostra situazione potrebbe essere diversa, ma nella maggior parte dei casi se un indice è disponibile è più importante di che tipo.

Pezzi e pezzi

Eseguendo una scansione di intervallo su un indice non cluster - sia perché la tabella è un heap o l'indice non è l'indice cluster - comporta la scansione dell'indice e quindi una ricerca sulla tabella per ogni hit. Questo può essere molto costoso, quindi a volte è più economico scansionare il tavolo. Tuttavia, puoi aggirare questo problema con un indice di copertura. Questo vale indipendentemente dal fatto che tu abbia raggruppato o meno il tuo tavolo.

Come ha sottolineato @gbn, non esiste un modo semplice per compattare un heap. Tuttavia, se la tabella aumenta gradualmente nel tempo - un caso molto comune - ci saranno pochi sprechi poiché lo spazio liberato dalle eliminazioni sarà riempito da nuovi dati.

Molte delle discussioni tra heap e tabelle raggruppate che ho visto fanno una curiosa discussione di paglia che un heap senza indici sia inferiore a una tabella cluster in quanto richiede sempre una scansione della tabella. Questo è certamente vero, ma il confronto più significativo è "grande tabella cluster ben indicizzata" vs "grande heap ben indicizzato". Se il tuo tavolo è molto piccolo o eseguirai sempre scansioni, non importa molto se lo cluster o no.

Poiché ogni indice in una tabella cluster fa riferimento all'indice cluster, sono in effetti tutti gli indici di copertura. Una query che fa riferimento a una colonna indicizzata e alle colonne del cluster può eseguire una scansione dell'indice senza alcuna ricerca nella tabella. Questo in genere non è utile se il tuo indice di clustering è una chiave sintetica, ma se è una chiave di business che dovresti comunque recuperare, è una bella funzionalità.

TL; DR

Sono un ragazzo di data warehousing, non un esperto OLTP. Per le tabelle di fatto, utilizzo quasi sempre un indice di clustering sul campo, che probabilmente avrà bisogno di scansioni di intervalli, in genere un campo data. Per le tabelle dimensionali, eseguo il clustering sul PK, quindi è preordinato per unire join con tabelle fact.

Esistono diversi motivi per utilizzare gli indici di clustering, ma se nessuna di queste ragioni si applica, il sovraccarico potrebbe non essere utile. Ho il sospetto che ci siano molti "l'abbiamo sempre fatto in questo modo" ed "è solo una buona pratica" dietro le persone che usano universalmente gli indici cluster. Prova entrambi con i tuoi dati e il tuo carico e vedi cosa funziona meglio.


5

Penso che dire "L'unico uso valido sia per le tabelle di gestione temporanea utilizzate nei processi di importazione / esportazione / ETL" è a dir poco restrittivo. Devi prendere il caso d'uso previsto di un determinato sistema e quindi scegliere in base ai meriti di heap o indicizzare le tabelle organizzate (lo so, un termine Oracle ma lo descrive bene).

Il nostro magazzino carica circa 1,5 miliardi di righe al giorno e deve supportare scritture ed elaborazioni concomitanti e letture. L'archivio relazionale supporta un database OLAP e quindi le letture tendono principalmente ad essere scansioni di tabelle. Anche i report e i feed a valle che vengono generati non sono in genere sufficientemente selettivi in ​​modo tale da rendere utile qualsiasi indice. Il sistema supporta una finestra scorrevole di dati e quindi una volta caricata una tabella raramente ci riscriviamo e data l'implementazione piuttosto scadente del partizionamento delle tabelle che richiede blocchi Sch-M per divisioni di partizioni, switch e fusioni rispetto ai blocchi Sch-S per letture ecc. , il sistema ha dovuto utilizzare molte tabelle, anche se abbiamo anche alcune tabelle partizionate. L'uso di molte tabelle facilita la segmentazione dei dati e i cicli di pulizia, riducendo al contempo la contesa.

Pertanto, l'overhead aggiunto di una tabella organizzata indice (tabella cluster) su alcune colonne arbitrarie rispetto alla possibilità di effettuare il bcp in un heap, elaborare le partizioni OLAP, eseguire alcune query di scansione delle tabelle e quindi rilasciarle dopo 3 giorni, significa che significa non ne vale la pena. Si noti che nel nostro caso i dati vengono restituiti da un cluster di grosse dimensioni, quindi non è possibile ordinare i dati, quindi l'inserimento in una tabella con un indice cluster potrebbe introdurre altri problemi come "hot spot", suddivisioni di pagina e simili.

Inoltre, penso che l'argomento sulle pagine disperse sia un po 'disonesto. Gli indici cluster possono anche avere le loro pagine sparse in tutto il file. È solo che dopo la reindicizzazione (presupponendo più di 1000 pagine) questo potrebbe essere migliore di un heap, ma poi anche tu devi reindicizzare.

È anche possibile risparmiare spazio usando colonne sparse e compressione se questo è un problema. È vero che in alcuni casi la selezione su una tabella con un indice cluster può essere più veloce ma è necessario soppesarla con le risorse necessarie per caricarlo e mantenerlo.

[Modifica] Probabilmente dovrei chiarire che solo le nostre tabelle dei fatti non partizionate sono un mucchio. Le tabelle partizionate e le tabelle delle dimensioni hanno tutti indici cluster per supportare ricerche efficienti, ecc. [Modifica2] Corretti da 2,5 miliardi a 1,5 miliardi. Tut, quei due numeri si trovano uno accanto all'altro. Cosa succede quando si digitano le risposte su un telefono immagino ...

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.