SQL Server supporta tabelle e indici partizionati. Quando una tabella o un indice partizionato viene partizionato, i suoi dati vengono divisi in unità che possono essere distribuite su più filegroup.
Pertanto, per creare una tabella partizionata in SQL Server, devi prima creare i filegroup che conterranno ciascuna partizione. È inoltre necessario creare una funzione di partizione e uno schema di partizione.
Quindi funziona così:
- Crea gruppo/i di file
- Crea una funzione di partizione
- Crea uno schema di partizione
- Crea la tabella partizionata
Di seguito è riportato un esempio di utilizzo di questi passaggi per creare una tabella con quattro partizioni.
Crea filegroup
Innanzitutto, aggiungiamo quattro filegroup al database chiamati Test , quindi specifica il file fisico per ciascuno di questi filegroup.
ALTER DATABASE Test
ADD FILEGROUP MoviesFg1;
GO
ALTER DATABASE Test
ADD FILEGROUP MoviesFg2;
GO
ALTER DATABASE Test
ADD FILEGROUP MoviesFg3;
GO
ALTER DATABASE Test
ADD FILEGROUP MoviesFg4;
ALTER DATABASE Test
ADD FILE
(
NAME = MoviesFg1dat,
FILENAME = '/var/opt/mssql/data/MoviesFg1dat.ndf',
SIZE = 5MB,
MAXSIZE = 100MB,
FILEGROWTH = 5MB
)
TO FILEGROUP MoviesFg1;
ALTER DATABASE Test
ADD FILE
(
NAME = MoviesFg2dat,
FILENAME = '/var/opt/mssql/data/MoviesFg2dat.ndf',
SIZE = 5MB,
MAXSIZE = 100MB,
FILEGROWTH = 5MB
)
TO FILEGROUP MoviesFg2;
GO
ALTER DATABASE Test
ADD FILE
(
NAME = MoviesFg3dat,
FILENAME = '/var/opt/mssql/data/MoviesFg3dat.ndf',
SIZE = 5MB,
MAXSIZE = 100MB,
FILEGROWTH = 5MB
)
TO FILEGROUP MoviesFg3;
GO
ALTER DATABASE Test
ADD FILE
(
NAME = MoviesFg4dat,
FILENAME = '/var/opt/mssql/data/MoviesFg4dat.ndf',
SIZE = 5MB,
MAXSIZE = 100MB,
FILEGROWTH = 5MB
)
TO FILEGROUP MoviesFg4;
GO
Dovrai modificare questo codice, a seconda delle tue esigenze. Dovrai anche modificare i percorsi dei file per adattarli al tuo ambiente. Ad esempio, se sei su Windows, il tuo percorso potrebbe assomigliare di più a D:\mssql\data\MoviesFg4dat.ndf
.
Inoltre, se hai bisogno di più partizioni, aggiungi più filegroup qui. Al contrario, se hai bisogno di meno partizioni, specifica qui meno filegroup.
Crea una funzione di partizione
Quindi creiamo una funzione di partizione chiamata MoviesPartitionFunction che partiziona la tabella in quattro partizioni.
CREATE PARTITION FUNCTION MoviesPartitionFunction (int)
AS RANGE LEFT FOR VALUES (1, 100, 1000);
GO
Il int part specifica il tipo di dati della colonna utilizzata per il partizionamento.
Tutti i tipi di dati sono validi per l'uso come colonne di partizionamento, tranne testo , ntesto , immagine , xml , indicatore orario , varchar(max) , nvarchar(max) , variabile(max) , tipi di dati alias o tipi di dati CLR definiti dall'utente.
Qui utilizzo tre valori limite (1, 100
e 1000
) per specificare quattro partizioni. Questi valori limite devono corrispondere o essere convertibili in modo implicito nel tipo di dati specificato tra parentesi dopo il nome della funzione di partizione.
Dati questi valori limite e il fatto che ho specificato un RANGE LEFT
partizione, le quattro partizioni conterranno i valori come specificato nella tabella seguente.
Partizione | Valori |
---|---|
1 | <= 1 |
2 | > 1 E <= 100 |
3 | > 100 E <=1000 |
4 | > 1000 |
Se avessi specificato un RANGE RIGHT
partizione, la ripartizione sarebbe leggermente diversa, come indicato nella tabella seguente.
Partizione | Valori |
---|---|
1 | < 1 |
2 | >= 1 E < 100 |
3 | >= 100 E < 1000 |
4 | >= 1000 |
Lo stesso concetto si applica se la colonna di partizionamento utilizza altri tipi di dati, come i valori di data/ora.
Crea uno schema di partizione
Quindi dobbiamo creare uno schema di partizione.
Uno schema di partizione associa le partizioni di una tabella o di un indice partizionato ai nuovi filegroup.
Nel nostro caso, il codice sarà simile a questo:
CREATE PARTITION SCHEME MoviesPartitionScheme
AS PARTITION MoviesPartitionFunction
TO (MoviesFg1, MoviesFg2, MoviesFg3, MoviesFg4);
GO
Si noti che si fa riferimento alla funzione di partizione creata nel passaggio precedente. Facciamo anche riferimento ai filegroup che abbiamo creato nel primo passaggio.
Crea la tabella partizionata
Finalmente possiamo creare la tabella partizionata.
CREATE TABLE Movies (
MovieId int IDENTITY PRIMARY KEY,
MovieName varchar(60)
)
ON MoviesPartitionScheme (MovieId);
GO
L'unica differenza tra questo e la creazione di una tabella non partizionata è che quando si crea una tabella partizionata, utilizziamo ON
argomento per specificare uno schema di partizione da utilizzare. Nel nostro caso, specifichiamo lo schema di partizione che abbiamo creato nel passaggio precedente e specifichiamo il MovieId colonna come colonna di partizionamento.
Noterai che il MovieId la colonna ha un tipo di dati int , che corrisponde ai valori limite specificati durante la creazione della funzione di partizione.
Nota che se utilizzi una colonna calcolata in una funzione di partizione, deve essere contrassegnata in modo esplicito PERSISTED
.
Verifica la funzione di partizione
Puoi usare sys.partition_functions
view per restituire tutte le funzioni della partizione.
SELECT * FROM sys.partition_functions;
Risultato (usando l'output verticale):
name | MoviesPartitionFunction function_id | 65536 type | R type_desc | RANGE fanout | 4 boundary_value_on_right | 0 is_system | 0 create_date | 2020-10-10 05:37:41.330 modify_date | 2020-10-10 05:37:41.330
Controlla lo schema di partizione
Puoi usare sys.partition_schemes
per controllare lo schema di partizione.
SELECT * FROM sys.partition_schemes;
Risultato (usando l'output verticale):
name | MoviesPartitionScheme data_space_id | 65601 type | PS type_desc | PARTITION_SCHEME is_default | 0 is_system | 0 function_id | 65536
In alternativa, puoi utilizzare la query seguente per restituire altri dettagli, come lo schema, la tabella, l'indice, ecc.
SELECT
object_schema_name(i.object_id) AS [Schema],
object_name(i.object_id) AS [Object],
i.name AS [Index],
s.name AS [Partition Scheme]
FROM sys.indexes i
INNER JOIN sys.partition_schemes s ON i.data_space_id = s.data_space_id;
Risultato (usando l'output verticale):
Schema | dbo Object | Movies Index | PK__Movies__4BD2941A0ED85ACA Partition Scheme | MoviesPartitionScheme
Controlla la tabella partizionata
Puoi eseguire sys.dm_db_partition_stats
view per restituire le informazioni sul conteggio delle pagine e delle righe per ogni partizione nel database corrente.
Ma eseguirlo prima di inserire qualsiasi dato nella tabella comporterà che la maggior parte delle statistiche sarà zero.
Quindi inserirò prima i dati.
INSERT INTO Movies
SELECT name FROM OtherDb.dbo.Movies;
Risultato:
(4079 rows affected)
Possiamo vedere che sono state inserite 4.079 righe.
Ora interroghiamo il sys.dm_db_partition_stats
visualizza.
SELECT *
FROM sys.dm_db_partition_stats
WHERE object_id = OBJECT_ID('dbo.Movies');
Risultato:
+-------------------+-------------+------------+--------------------+--------------------------+--------------------------+------------------------------+-----------------------+---------------------------+--------------------------------+------------------------------------+-------------------+-----------------------+-------------+ | partition_id | object_id | index_id | partition_number | in_row_data_page_count | in_row_used_page_count | in_row_reserved_page_count | lob_used_page_count | lob_reserved_page_count | row_overflow_used_page_count | row_overflow_reserved_page_count | used_page_count | reserved_page_count | row_count | |-------------------+-------------+------------+--------------------+--------------------------+--------------------------+------------------------------+-----------------------+---------------------------+--------------------------------+------------------------------------+-------------------+-----------------------+-------------| | 72057594048413696 | 2030630277 | 1 | 1 | 1 | 2 | 9 | 0 | 0 | 0 | 0 | 2 | 9 | 1 | | 72057594048479232 | 2030630277 | 1 | 2 | 1 | 2 | 9 | 0 | 0 | 0 | 0 | 2 | 9 | 99 | | 72057594048544768 | 2030630277 | 1 | 3 | 3 | 5 | 25 | 0 | 0 | 0 | 0 | 5 | 25 | 900 | | 72057594048610304 | 2030630277 | 1 | 4 | 10 | 12 | 33 | 0 | 0 | 0 | 0 | 12 | 33 | 3079 | +-------------------+-------------+------------+--------------------+--------------------------+--------------------------+------------------------------+-----------------------+---------------------------+--------------------------------+------------------------------------+-------------------+-----------------------+-------------+
Questa visualizzazione restituisce molte colonne, quindi restringiamo le colonne a solo un paio.
SELECT
partition_number,
row_count
FROM sys.dm_db_partition_stats
WHERE object_id = OBJECT_ID('dbo.Movies');
Risultato:
+--------------------+-------------+ | partition_number | row_count | |--------------------+-------------| | 1 | 1 | | 2 | 99 | | 3 | 900 | | 4 | 3079 | +--------------------+-------------+
Possiamo vedere come le righe sono allocate tra le partizioni. Sono allocati esattamente come abbiamo specificato nella funzione di partizione. Le righe totalizzano 4.079, che corrisponde esattamente al numero di righe che abbiamo inserito.
Tuttavia, vale la pena notare che la documentazione Microsoft in realtà afferma che questa colonna è solo un approssimativo conteggio delle righe in ogni partizione.
Migliori prassi
Microsoft consiglia di mantenere sempre le partizioni vuote su entrambe le estremità dell'intervallo di partizioni.
Questo è nel caso in cui sia necessario dividere o unire le partizioni in futuro.
Il motivo di questa raccomandazione è garantire che la divisione della partizione e l'unione delle partizioni non comportino alcun movimento di dati imprevisto.
Pertanto, dati i dati nel mio esempio, potrei cambiare la funzione di partizione in modo che assomigli a qualcosa del genere:
CREATE PARTITION FUNCTION MoviesPartitionFunction (int)
AS RANGE LEFT FOR VALUES (-1, 100, 10000);
GO
Oppure, se prevedo più di 10.000 righe, potrei utilizzare un numero maggiore (o creare più partizioni).
Se dovessi ricreare nuovamente tutti i passaggi, per creare la mia tabella partizionata, le statistiche della mia partizione sarebbero così:
SELECT
partition_number,
row_count
FROM sys.dm_db_partition_stats
WHERE object_id = OBJECT_ID('dbo.Movies');
Risultato:
+--------------------+-------------+ | partition_number | row_count | |--------------------+-------------| | 1 | 0 | | 2 | 100 | | 3 | 3979 | | 4 | 0 | +--------------------+-------------+
Ora i miei dati sono concentrati nelle due partizioni centrali e le partizioni su entrambe le estremità sono vuote.