Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Esercitazione sul partizionamento delle tabelle e sulle partizioni di SQL Server

Problema

In questo articolo, ci concentreremo sulla dimostrazione del partizionamento delle tabelle. La spiegazione più semplice del partizionamento delle tabelle può essere chiamata divisione di tabelle grandi in tabelle piccole. Questo argomento fornisce scalabilità e gestibilità.

Che cos'è il partizionamento delle tabelle in SQL Server?

Supponiamo di avere un tavolo e che cresca di giorno in giorno. In questo caso, la tabella può causare alcuni problemi che devono essere risolti con i passaggi definiti di seguito:

  • Mantieni questa tabella. Ci vorrà molto tempo e consumerà più risorse (CPU, IO ecc.).
  • Esegui il backup.
  • Problemi di blocco.

Per i motivi sopra menzionati, abbiamo bisogno di un partizionamento della tabella. Questo approccio ha i seguenti vantaggi:

  • Capacità di gestione:se dividiamo la tabella, possiamo gestire ogni partizione della tabella. Ad esempio, possiamo creare una sola partizione della tabella.
  • Capacità di archiviazione:alcune partizioni della tabella vengono utilizzate solo per questo motivo. Non è necessario eseguire il backup di questa partizione della tabella. Possiamo utilizzare un backup di filegroup ed eseguirne il backup solo modificando una partizione della tabella.
  • Prestazioni delle query:Query Optimizer di SQL Server decide di utilizzare l'eliminazione della partizione. Significa che SQL Server non effettua alcuna ricerca per la partizione non correlata della tabella.

Partizionamento di tabelle verticali e orizzontali in SQL Server

Il partizionamento delle tabelle è un concetto generale. Esistono diversi tipi di partizionamento che funzionano per casi particolari. I più essenziali e ampiamente utilizzati sono i due approcci:partizione verticale e partizione orizzontale.

La specificità di ogni tipo riflette l'essenza di una tabella come struttura composta da colonne e righe:

• Il partizionamento verticale divide la tabella in colonne.
• Il partizionamento orizzontale divide la tabella in righe.

L'esempio più tipico del partizionamento verticale della tabella è una tabella dei dipendenti con i loro dettagli:nomi, e-mail, numeri di telefono, indirizzi, compleanni, occupazioni, stipendi e tutte le altre informazioni che potrebbero essere necessarie. Una parte di tali dati è riservata. Inoltre, nella maggior parte dei casi, gli operatori necessitano solo di alcuni dati di base come nomi e indirizzi email.

Il partizionamento verticale crea diverse tabelle "più strette" con i dati necessari a portata di mano. Le query hanno come target solo una parte specifica. In questo modo, le aziende riducono il carico, accelerano le attività e assicurano che i dati riservati non vengano rivelati.

Il partizionamento orizzontale della tabella comporta la divisione di una tabella generale in più tabelle più piccole, in cui ciascuna tabella delle particelle ha lo stesso numero di colonne, ma il numero di righe è inferiore. È un approccio standard per tabelle eccessive con dati cronologici.

Ad esempio, una tabella con i dati dell'intero anno può essere suddivisa in sezioni più piccole per ogni mese o settimana. Quindi, la query riguarderà solo una tabella specifica più piccola. Il partizionamento orizzontale migliora la scalabilità dei volumi di dati con la loro crescita. Le tabelle partizionate rimarranno più piccole e facili da elaborare.

Qualsiasi partizionamento di tabelle in SQL Server dovrebbe essere considerato con attenzione. A volte devi richiedere i dati da più tabelle partizionate contemporaneamente, quindi avrai bisogno di JOIN nelle query. Inoltre, il partizionamento verticale può comunque comportare tabelle di grandi dimensioni e dovrai dividerle di più. Nel tuo lavoro, dovresti fare affidamento sulle decisioni per i tuoi scopi aziendali specifici.

Ora che abbiamo chiarito il concetto di partizionamento delle tabelle in SQL Server, è il momento di procedere alla dimostrazione.

Eviteremo qualsiasi script T-SQL e gestiremo tutti i passaggi della partizione della tabella con la procedura guidata di partizionamento di SQL Server.

Di cosa hai bisogno per creare partizioni di database SQL?

  • Database di esempio di WideWorldImporters
  • Edizione per sviluppatori SQL Server 2017

L'immagine seguente ci mostra come progettare una partizione di una tabella. Creeremo una partizione di una tabella per anni e individueremo diversi filegroup.

A questo punto creeremo due filegroup (FG_2013, FG_2014). Fare clic con il pulsante destro del mouse su un database, quindi fare clic sulla scheda Filegroup.

Ora collegheremo i gruppi di file ai nuovi file pdf.

La nostra struttura di archiviazione del database è pronta per il partizionamento delle tabelle. Individueremo la tabella che vogliamo partizionare e avvieremo la procedura guidata Crea partizione.

Nello screenshot qui sotto, selezioneremo una colonna su cui vogliamo applicare la funzione di partizione. La colonna selezionata è "Data fattura".

Nelle prossime due schermate, nomineremo una funzione di partizione e uno schema di partizione.

Una funzione di partizione definirà come eseguire la partizione per le righe [Sales].[Invoices] in base alla colonna InvoiceDate.

Uno schema di partizione definirà le mappe per le righe Sales.Invoices in filegroup.

Assegna le partizioni ai filegroup e imposta i limiti.

Limite sinistro/destro definisce il lato di ciascun intervallo di valori limite che può essere sinistro o destro. Imposteremo i limiti in questo modo e faremo clic su Stima spazio di archiviazione. Questa opzione ci fornisce le informazioni sul numero di righe da posizionare nei confini.

Infine, selezioneremo Esegui immediatamente e quindi faremo clic su Avanti.

Una volta completata l'operazione, fai clic su Chiudi.

Come puoi vedere, la nostra tabella Sales.Invoices è stata partizionata. Questa query mostrerà i dettagli della tabella partizionata.

SELECT
  OBJECT_SCHEMA_NAME(pstats.object_id) AS SchemaName
  ,OBJECT_NAME(pstats.object_id) AS TableName
  ,ps.name AS PartitionSchemeName
  ,ds.name AS PartitionFilegroupName
  ,pf.name AS PartitionFunctionName
  ,CASE pf.boundary_value_on_right WHEN 0 THEN 'Range Left' ELSE 'Range Right' END AS PartitionFunctionRange
  ,CASE pf.boundary_value_on_right WHEN 0 THEN 'Upper Boundary' ELSE 'Lower Boundary' END AS PartitionBoundary
  ,prv.value AS PartitionBoundaryValue
  ,c.name AS PartitionKey
  ,CASE 
    WHEN pf.boundary_value_on_right = 0 
    THEN c.name + ' > ' + CAST(ISNULL(LAG(prv.value) OVER(PARTITION BY pstats.object_id ORDER BY pstats.object_id, pstats.partition_number), 'Infinity') AS VARCHAR(100)) + ' and ' + c.name + ' <= ' + CAST(ISNULL(prv.value, 'Infinity') AS VARCHAR(100)) 
    ELSE c.name + ' >= ' + CAST(ISNULL(prv.value, 'Infinity') AS VARCHAR(100))  + ' and ' + c.name + ' < ' + CAST(ISNULL(LEAD(prv.value) OVER(PARTITION BY pstats.object_id ORDER BY pstats.object_id, pstats.partition_number), 'Infinity') AS VARCHAR(100))
  END AS PartitionRange
  ,pstats.partition_number AS PartitionNumber
  ,pstats.row_count AS PartitionRowCount
  ,p.data_compression_desc AS DataCompression
FROM sys.dm_db_partition_stats AS pstats
INNER JOIN sys.partitions AS p ON pstats.partition_id = p.partition_id
INNER JOIN sys.destination_data_spaces AS dds ON pstats.partition_number = dds.destination_id
INNER JOIN sys.data_spaces AS ds ON dds.data_space_id = ds.data_space_id
INNER JOIN sys.partition_schemes AS ps ON dds.partition_scheme_id = ps.data_space_id
INNER JOIN sys.partition_functions AS pf ON ps.function_id = pf.function_id
INNER JOIN sys.indexes AS i ON pstats.object_id = i.object_id AND pstats.index_id = i.index_id AND dds.partition_scheme_id = i.data_space_id AND i.type <= 1 /* Heap or Clustered Index */
INNER JOIN sys.index_columns AS ic ON i.index_id = ic.index_id AND i.object_id = ic.object_id AND ic.partition_ordinal > 0
INNER JOIN sys.columns AS c ON pstats.object_id = c.object_id AND ic.column_id = c.column_id
LEFT JOIN sys.partition_range_values AS prv ON pf.function_id = prv.function_id AND pstats.partition_number = (CASE pf.boundary_value_on_right WHEN 0 THEN prv.boundary_id ELSE (prv.boundary_id+1) END)
WHERE pstats.object_id = OBJECT_ID('Sales.Invoices')
ORDER BY TableName, PartitionNumber;

SM Prestazioni di partizionamento di SQL Server

Confronteremo le prestazioni della tabella partizionata e non partizionata per la stessa tabella. Per fare ciò, utilizza la query seguente e attiva Includi piano di esecuzione effettivo.

DECLARE @Dt as date  = '20131231'
SELECT COUNT(InvoiceDate)
  FROM [Sales].[Invoices]
  where InvoiceDate < @Dt

Quando esaminiamo il piano di esecuzione, veniamo a sapere che include le proprietà "Partitioned", "Actual Partition Count" e "Actual Partitioned Accessed".

La Proprietà partizionata indica che questa tabella è abilitata per la partizione.

Il conteggio effettivo delle partizioni è il numero totale di partizioni lette dal motore di SQL Server.

Il accesso partizionato effettivo la proprietà è i numeri di partizione valutati dal motore di SQL Server. SQL Server elimina l'accesso ad altre partizioni in quanto viene chiamato eliminazione della partizione e ottiene un vantaggio sulle prestazioni delle query.

Ora, guarda il piano di esecuzione della tabella non partizionata.

La principale differenza tra questi due piani di esecuzione è Numero di righe lette poiché questa proprietà indica quante righe vengono lette per questa query. Come puoi vedere dal grafico di compressione sottostante, i valori della tabella partizionata sono troppo bassi. Per questo motivo consumerà un basso IO.

Quindi, esegui la query ed esamina il piano di esecuzione.

DECLARE @DtBeg as date  = '20140502'
DECLARE @DtEnd as date  = '20140701'

SELECT COUNT(InvoiceDate)
  FROM [Sales].[Invoices]
  where InvoiceDate between @DtBeg and @DtEnd

Escalation del blocco a livello di partizione

L'escalation dei blocchi è un meccanismo utilizzato da SQL Server Lock Manager. Organizza per bloccare un livello di oggetti. Quando il numero di righe da bloccare aumenta, il gestore blocchi modifica un oggetto di blocco. Questo è il livello gerarchico dell'escalation dei blocchi "Riga -> Pagina -> Tabella -> Database". Ma, nella tabella partizionata, possiamo bloccare una partizione poiché aumenta la concorrenza e le prestazioni. Il livello predefinito di escalation dei blocchi è "TABLE" in SQL Server.

Esegui la query utilizzando l'istruzione UPDATE di seguito.

BEGIN TRAN
DECLARE @Dt as date  = '20131221'
UPDATE [Sales].[Invoices] SET CreditNoteReason = 'xxx'   where InvoiceDate < @Dt
SP_LOCK

La casella rossa definisce un blocco esclusivo che garantisce che non possano essere apportati più aggiornamenti alla stessa risorsa contemporaneamente. Si verifica nella tabella Fatture.

Ora imposteremo la modalità di escalation per la tabella Sales.Invoices per automatizzarla ed eseguire nuovamente la query.

ALTER TABLE Sales.Invoices SET (LOCK_ESCALATION = AUTO)

Ora, la casella rossa definisce il blocco esclusivo del rientro che protegge i blocchi esclusivi richiesti o acquisiti su alcune risorse inferiori nella gerarchia. In breve, questo livello di blocco ci consente di aggiornare o eliminare altre partizioni di tabelle. Ciò significa che possiamo avviare un altro aggiornamento o inserire un'altra partizione della tabella.

Nei post precedenti, abbiamo anche esplorato il problema del passaggio tra il partizionamento delle tabelle e fornito la procedura dettagliata. Queste informazioni possono esserti di aiuto se affronti questi casi. Fare riferimento all'articolo per ulteriori informazioni.

Riferimenti

  1. Modalità di blocco
  2. Tabelle e indici partizionati