A che punto dovrei dividere o dividere una tabella molto grande ma semplice


8

Il nostro sito ha alcune tabelle grandi ma semplici (INT, INT, DATE) per le statistiche. Ogni tabella ha fino a 300.000.000 di righe e diventa più grande ogni giorno.

Il provider di hosting ha suggerito di dividere o dividere le tabelle e ho visto questa raccomandazione altrove in numerose occasioni.

Però...

Faccio fatica a conciliare questo consiglio con la capacità massima dichiarata per SQL Server - una dimensione del database di 524.272 terabyte, con le righe della tabella limitate solo dalla "memoria disponibile".

Sulla base di tali dati, la tabella sopra descritta potrebbe facilmente avere centilioni di file (10 alla potenza di 303).

Ah ah potresti dire, c'è una differenza tra CAPACITÀ e PRESTAZIONI.

Ma praticamente in ogni domanda sulle prestazioni di SQL Server la risposta è "Dipende dalla progettazione della tabella e dalla progettazione della query".

Questo è il motivo per cui sto ponendo questa domanda. Il design del tavolo non potrebbe essere molto più semplice. Né potrebbero le query che sono semplici operazioni di conteggio (*) basate su un campo ID indicizzato.


Le tabelle di partizionamento sono qualcosa che pianifichi nella progettazione del tuo database, prima di scrivere i dati preferibilmente. È molto più difficile e noioso farlo dopo il fatto.

1
Dipende più dal tuo scenario: le prestazioni vanno bene? Puoi archiviare alcuni dei dati? Le tabelle sono così importanti per eseguire il backup / ripristino in modo efficiente? Sono compressi? Sarebbe stato bello partizionare dal primo giorno, ma il giorno migliore successivo è oggi se sei preoccupato per le prestazioni future se vuoi seguire le migliori pratiche.
LowlyDBA

2
Penso che con questa quantità di dati dovrai dividere il tuo database a livello di architettura, database OLTP e database OLAP, il tuo database applicativo "OLTP" dovrebbe mantenere solo i dati minimi richiesti per l'applicazione e il business, il resto dovrebbe essere scaricato in un dato magazzino "OLAP". Per quanto riguarda la domanda su quando dovresti iniziare a partizionare i tuoi tavoli dai un'occhiata a questo articolo di Kendra LittleHow To Decide if You Should Use Table Partitioning
M.Ali

3
Le prestazioni non superano mai il fatto che un tavolo è grande. In effetti ciò che è grande per molti è piccolo per alcuni. Comprendi quali operazioni vengono eseguite più rapidamente e quali rallentano con il partizionamento. Il partizionamento non è un passaggio più veloce. È un interruttore per lo più lento e alcune cose diventano incredibilmente veloci.
usr

4
Consiglio vivamente il video di formazione MCM sul partizionamento di Kimberly Tripp.
Paul White 9

Risposte:


10

C'è una ragione per cui il consiglio generale è che dipende dal design del tavolo e dalle domande su di esso. La mia risposta agli altri tuoi post su Stack Exchange dice altrettanto. Dire "query che sono semplici operazioni di conteggio (*) basate su un campo ID indicizzato" non fornisce molte informazioni poiché non dice nulla della cardinalità dell'insieme di righe in esame. Le cose che puoi fare per mitigare i problemi (attualmente percepiti) sono:

  1. Partizionamento. In particolare, i dati sembrano essere dati di tipo registrazione. Suppongo che tu voglia ottenere statistiche per alcune unità di tempo (ad esempio "widget al giorno" o "whozits per ora"). Partiziona secondo il tuo quantum (cioè giorni o ore negli esempi precedenti) e sposta le partizioni in gruppi di file di sola lettura occasionalmente

  2. In una nota correlata, se i dati sono in scrittura singola, prendere in considerazione la pre-aggregazione dei dati una volta che il periodo di tempo non è più attivo. Cioè, perché devo continuare a contare quanti eventi sono accaduti in un giorno di tre anni fa se quei dati non cambieranno mai? Una volta che il giorno è finito, conta tutto in quel giorno, memorizzalo altrove e non contarlo mai più. In effetti, se non hai mai bisogno dei dati dettagliati (cioè fai solo aggregazioni contro di essi), considera di eliminarli dopo averli contati. Se si implementa questa idea, è possibile diventare ancora più intelligenti con indici filtrati che coprono solo il periodo "attivo" che renderà le tue domande più veloci perché non copriranno la stragrande maggioranza dei tuoi dati

Ma, come suggerisce il mio consiglio nell'altro post, l'unico modo per conoscerlo con certezza è caricarlo con una quantità ragionevole di dati e provarlo. Tutto ciò che possiamo fare qui è dire cosa probabilmente funzionerà nel caso generale. Senza le specifiche del tuo hardware, i tuoi dati e le tue domande, tutto ciò che possiamo fare è indovinare. E potresti scoprire che, una volta eseguito il test, sto proponendo che la risposta sia "non c'è niente da fare" perché funziona perfettamente così com'è.


Grazie Ben. Sto iniziando ad apprezzare che ci sono più variabili in gioco di quanto pensassi inizialmente. E accetto che, praticamente parlando, "provalo e vedi" è l'approccio più sensato. Ma poiché SQL Server è essenzialmente un programma (anche se molto complicato), una parte di me è frustrata da questa mancanza di prevedibilità.
Martin Hansen Lennox,

1
@MartinHansenLennox e Ben: sono assolutamente d'accordo con l'approccio "provalo" piuttosto che ascoltare solo consigli o speculazioni personali. Tuttavia, consiglierei di indicare più esplicitamente in quel paragrafo cosa significhi davvero provarlo. È molto più che caricarlo ed eseguire query. I test devono includere l'aggiunta incrementale di dati per vedere se / come le cose cambiano quando le statistiche cambiano e gli indici vengono frammentati, ecc. E provare a eseguire il backup, il ripristino, la ricostruzione di indici, ecc. Va notato che gli indici partizionati, a partire dal 2012, non sono più ottenere un aggiornamento completo dello stato durante la ricostruzione.
Solomon Rutzky,

@MartinHansenLennox: hai ragione ad essere frustrato dall'approccio "provalo e vedi". SQL Server è molto prevedibile ed è almeno in teoria possibile analizzare il problema prima di provarlo. Tuttavia, la quantità di conoscenze di base necessarie per farlo spesso rende questo difficile.
Thomas Kejser il

7

Adotterò un approccio diverso e noterò che il partizionamento ( in SQL Server ) è principalmente una funzionalità di gestione dei dati con le prestazioni della query come possibile risultato secondario, a seconda di come la gestisci . 1

Come notato nell'articolo collegato, il vantaggio principale del partizionamento è che puoi spostare rapidamente i dati usando il cambio di partizione . Ad esempio, è possibile archiviare i dati "più freddi" in una memoria più lenta e mantenere i dati "caldi" in una memoria veloce. A intervalli regolari programmati, è possibile archiviare rapidamente i dati facendoli scorrere per archiviare le partizioni senza dover passare attraverso il processo di attesa di un ETL per eseguire il trasferimento. Come notato in uno dei primi commenti alla tua domanda, tuttavia, ciò richiederà un po 'di attenta riflessione e pianificazione prima di implementarlo. Inoltre, a seconda dell'edizione di SQL Server utilizzata (Enterprise), è possibile sfruttare la compressione dei dati per comprimere le singole partizioni.

Per quanto riguarda le prestazioni, è possibile modificare l'escalation dei blocchi su AUTO(impostazione predefinita TABLE) in questo modo :

ALTER TABLE dbo.T1 SET (LOCK_ESCALATION = AUTO);
GO

Inoltre, potresti ottenere l'eliminazione della partizione ma i tuoi schemi di query dovrebbero adattarsi a un modello molto specifico e ripetibile all'interno del tuo sistema: la chiave di partizionamento e la chiave di clustering e qualsiasi chiave unica diventano interconnesse e molto importanti . Se questo equilibrio non viene considerato riconosciuto e progettato intorno, si finisce con incubi prestazionali.

Con l'avvento di SQL Server 2014, puoi anche trarre vantaggio dalle statistiche incrementali che sono molto utili se monitori e aggiorni / crei staticamente proattivamente su tabelle di grandi dimensioni.

Quindi, a che punto una tabella dovrebbe essere partizionata? Ciò dipende dal carico di lavoro delle query, dal profilo dei dati, ma, soprattutto, dipende da quale delle funzioni di gestione del partizionamento è assolutamente necessario sfruttare. Il partizionamento non è per le prestazioni delle query, è principalmente per la gestione e l'amministrazione dei dati.


2
"Il partizionamento non è per le prestazioni delle query, è principalmente per la gestione e l'amministrazione dei dati" - sembra ovvio quando lo dici, ma non l'avevo mai capito prima. Ottimi collegamenti, grazie
Martin Hansen Lennox,

Grazie per aver menzionato che questa funzione è principalmente per la gestione e non per le prestazioni. Raramente vedo che essere menzionato ed è abbastanza frustrante.
Solomon Rutzky,

1
@MartinHansenLennox: ci sono grandi usi del partizionamento anche per le prestazioni. Ad esempio, se si utilizzano trucchi di partizionamento hash e per valori con cardinalità bassa.
Thomas Kejser,

7

Prima di decidere la dimensione della partizione, considerare le implicazioni del partizionamento del piano di query. Dal punto di vista puramente prestazionale, le partizioni fungono da forma di indice a grana grossa. Ciò può fornire prestazioni extra, ma è anche una fonte di regressioni delle prestazioni, soprattutto se la chiave di partizione non viene visualizzata in tutte le query. Da qui, presumo che tu abbia già fatto questi compiti (come sembra che tu abbia fatto).

Una buona regola empirica per la dimensione desiderata di una partizione è: circa la metà della dimensione della DRAM che hai sulla scatola. Il motivo di questa raccomandazione è:

  1. È possibile ricostruire gli indici sulla partizione senza versare tempdb. questo è MOLTO più veloce che se si utilizza l'accesso al disco (anche con SSD).
  2. Mentre esegui questa ricostruzione, puoi comunque conservare un'intera partizione (in genere la più recente) in DRAM per mantenere le prestazioni della query in costante evoluzione.

In altre parole, si desidera avere abbastanza DRAM per contenere due partizioni e la dimensione della partizione desiderata dipende dalla macchina su cui si esegue. Le macchine più grandi possono gestire comodamente partizioni più grandi.

Nota che questa guida fornisce anche una dimensione minima per tempdb: Almeno la dimensione della tua partizione più grande (quindi PUOI versare la build dell'indice lì se non c'è abbastanza DRAM quando ricostruisci un indice).

È possibile prendere in considerazione dimensioni di partizione inferiori rispetto a questa, ma in tal caso, ciò è in genere destinato all'ottimizzazione delle prestazioni e non a supportare la gestibilità dei dati.

Ci sono molti altri trucchi che puoi giocare con le partizioni. Ad esempio, la compressione, l'aggregazione o l'utilizzo di Fill Factor 100 su partizioni di sola lettura. Ma il principio di base è ancora: cerca di mantenere ogni blocco di dati che gestisci più piccolo di DRAM.

PS: Felice di vederti non prendere "dipende" come risposta, chiedi sempre un metodo per ottenere la risposta.


Grazie Thomas, un buon consiglio, apprezzo particolarmente le spiegazioni sul dimensionamento delle partizioni.
Martin Hansen Lennox,

7

Il partizionamento delle tabelle, come molte altre funzionalità, è abbastanza spesso (o forse anche il più delle volte?) Usato in modo inappropriato. Tutte le precauzioni che avrei dato sono state ben espresse nella risposta di @ swasheck .

Inoltre, un'alternativa da considerare sono le viste partizionate. Questo è un modo per mantenere tabelle completamente separate ma collegandole insieme tramite UNION ALL in una vista. Ogni tabella richiede un CONTROLLO VINCITORE che impone quale intervallo di dati contiene ciascuna tabella. L'ottimizzatore conosce questo costrutto e dovrebbe accedere solo alle tabelle sottostanti richieste da una query utilizzando la vista (non ricordo tutti i requisiti per avere questo lavoro come previsto, quindi vedi il link CREATE VIEW in fondo, ma L'ho installato prima e non è stato difficile farlo funzionare come previsto).

Ci sono sicuramente alcune restrizioni, e il principale svantaggio è che è meno trasparente rispetto al partizionamento delle tabelle. Tuttavia, un vantaggio principale è che si tratta di tabelle separate e quindi le statistiche sono completamente separate, mentre con una tabella partizionata sono per l'intera tabella (anche se, a partire da SQL Server 2014, è possibile aggiornare le statistiche per partizione).

Se non si intende utilizzare la commutazione delle partizioni in entrata e in uscita, è necessario considerare questa opzione. Soprattutto se i dati più vecchi non cambiano molto poiché le tabelle che contengono i dati più vecchi non hanno bisogno di aggiornare gli indici / le statistiche quasi altrettanto spesso (o forse mai se i dati non cambiano mai).

Un altro aspetto negativo del partizionamento delle tabelle che non viene menzionato / non notato fin troppo spesso è che a partire da SQL Server 2012 non si ottengono più "STATISTICHE AGGIORNATE" CON FULLSCAN quando si ricostruiscono indici partizionati. Ottieni ancora questo aggiornamento statistiche con una ricostruzione su indici non partizionati, che gli indici sulle tabelle in una vista partizionata sarebbero :).

Per ulteriori informazioni sulle viste partizionate, consultare la pagina MSDN per CREATE VIEW e cercare la sezione "Viste partizionate" in "Osservazioni".


2
Ottimo punto sulle statistiche aggiornate. Le viste indicizzate risolvono molti problemi di partizionamento se è possibile gestire l'impatto dell'ottimizzatore.
Thomas Kejser il
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.