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

Creare una tabella partizionata in SQL Server (T-SQL)

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ì:

  1. Crea gruppo/i di file
  2. Crea una funzione di partizione
  3. Crea uno schema di partizione
  4. 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.