Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Créer une table partitionnée dans SQL Server (T-SQL)

SQL Server prend en charge les tables et les index partitionnés. Lorsqu'une table ou un index partitionné est partitionné, ses données sont divisées en unités qui peuvent être réparties sur plusieurs groupes de fichiers.

Par conséquent, pour créer une table partitionnée dans SQL Server, vous devez d'abord créer le ou les groupes de fichiers qui contiendront chaque partition. Vous devez également créer une fonction de partition et un schéma de partition.

Donc ça se passe comme ça :

  1. Créer des groupes de fichiers
  2. Créer une fonction de partition
  3. Créer un schéma de partition
  4. Créer la table partitionnée

Vous trouverez ci-dessous un exemple d'utilisation de ces étapes pour créer une table avec quatre partitions.

Créer des groupes de fichiers

Tout d'abord, nous ajoutons quatre groupes de fichiers à la base de données appelée Test , puis spécifiez le fichier physique pour chacun de ces groupes de fichiers.

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  

Vous devrez modifier ce code en fonction de vos besoins. Vous devrez également modifier les chemins d'accès aux fichiers en fonction de votre environnement. Par exemple, si vous êtes sous Windows, votre chemin pourrait ressembler davantage à D:\mssql\data\MoviesFg4dat.ndf .

De plus, si vous avez besoin de plus de partitions, ajoutez plus de groupes de fichiers ici. Inversement, si vous avez besoin de moins de partitions, spécifiez moins de groupes de fichiers ici.

Créer une fonction de partition

Ensuite, nous créons une fonction de partition appelée MoviesPartitionFunction qui divisera la table en quatre partitions.

CREATE PARTITION FUNCTION MoviesPartitionFunction (int)  
    AS RANGE LEFT FOR VALUES (1, 100, 1000);
GO

Le int part spécifie le type de données de la colonne utilisée pour le partitionnement.

Tous les types de données sont valides pour une utilisation en tant que colonnes de partitionnement, à l'exception de texte , texte , image , xml , horodatage , varchar(max) , nvarchar(max) , varbinaire(max) , des types de données d'alias ou des types de données CLR définis par l'utilisateur.

Ici, j'utilise trois valeurs limites (1, 100 , et 1000 ) pour spécifier quatre partitions. Ces valeurs limites doivent correspondre ou être implicitement convertibles en type de données spécifié entre parenthèses après le nom de la fonction de partition.

Compte tenu de ces valeurs limites et du fait que j'ai spécifié un RANGE LEFT partition, les quatre partitions contiendront les valeurs spécifiées dans le tableau suivant.

Partitionner Valeurs
1 <= 1
2 1 ET <= 100
3 100 ET <=1000
4 1000

Si j'avais spécifié un RANGE RIGHT partition, la répartition serait légèrement différente, comme indiqué dans le tableau suivant.

Partitionner Valeurs
1 1
2 >= 1 ET < 100
3 >= 100 ET < 1000
4 >= 1000

Le même concept s'applique si la colonne de partitionnement utilise d'autres types de données, tels que des valeurs de date/heure.

Créer un schéma de partition

Ensuite, nous devons créer un schéma de partition.

Un schéma de partition mappe les partitions d'une table ou d'un index partitionné vers les nouveaux groupes de fichiers.

Dans notre cas, le code ressemblera à ceci :

CREATE PARTITION SCHEME MoviesPartitionScheme  
    AS PARTITION MoviesPartitionFunction  
    TO (MoviesFg1, MoviesFg2, MoviesFg3, MoviesFg4);  
GO

Notez que nous faisons référence à la fonction de partition que nous avons créée à l'étape précédente. Nous référençons également les groupes de fichiers que nous avons créés lors de la première étape.

Créer la table partitionnée

Enfin, nous pouvons créer la table partitionnée.

CREATE TABLE Movies (
    MovieId int IDENTITY PRIMARY KEY, 
    MovieName varchar(60)
    )  
    ON MoviesPartitionScheme (MovieId);  
GO

La seule différence entre cela et la création d'une table non partitionnée est que lors de la création d'une table partitionnée, nous utilisons le ON argument pour spécifier un schéma de partition à utiliser. Dans notre cas, nous spécifions le schéma de partition que nous avons créé à l'étape précédente et spécifions le MovieId colonne comme colonne de partitionnement.

Vous remarquerez que le MovieId la colonne a un type de données int , qui correspond aux valeurs limites que nous avons spécifiées lors de la création de la fonction de partition.

Notez que si vous utilisez une colonne calculée dans une fonction de partition, elle doit être explicitement marquée PERSISTED .

Vérifier la fonction de partition

Vous pouvez utiliser les sys.partition_functions view pour retourner toutes les fonctions de partition.

SELECT * FROM sys.partition_functions;

Résultat (en utilisant la sortie 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

Vérifier le schéma de partition

Vous pouvez utiliser sys.partition_schemes pour vérifier le schéma de partition.

SELECT * FROM sys.partition_schemes;

Résultat (en utilisant la sortie verticale) :

name          | MoviesPartitionScheme
data_space_id | 65601
type          | PS
type_desc     | PARTITION_SCHEME
is_default    | 0
is_system     | 0
function_id   | 65536

Vous pouvez également utiliser la requête suivante pour renvoyer d'autres détails, tels que le schéma, la table, l'index, etc.

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;

Résultat (en utilisant la sortie verticale) :

Schema           | dbo
Object           | Movies
Index            | PK__Movies__4BD2941A0ED85ACA
Partition Scheme | MoviesPartitionScheme

Vérifiez la table partitionnée

Vous pouvez exécuter le sys.dm_db_partition_stats view pour renvoyer des informations sur le nombre de pages et de lignes pour chaque partition de la base de données actuelle.

Mais l'exécuter avant d'insérer des données dans le tableau entraînera la plupart des statistiques à zéro.

Je vais donc d'abord insérer des données.

INSERT INTO Movies
SELECT name FROM OtherDb.dbo.Movies;

Résultat :

(4079 rows affected)

Nous pouvons voir que 4 079 lignes ont été insérées.

Interrogeons maintenant le sys.dm_db_partition_stats vue.

SELECT *
FROM sys.dm_db_partition_stats
WHERE object_id = OBJECT_ID('dbo.Movies');

Résultat :

+-------------------+-------------+------------+--------------------+--------------------------+--------------------------+------------------------------+-----------------------+---------------------------+--------------------------------+------------------------------------+-------------------+-----------------------+-------------+
| 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        |
+-------------------+-------------+------------+--------------------+--------------------------+--------------------------+------------------------------+-----------------------+---------------------------+--------------------------------+------------------------------------+-------------------+-----------------------+-------------+

Cette vue renvoie un grand nombre de colonnes. Réduisons donc les colonnes à quelques-unes seulement.

SELECT 
    partition_number,
    row_count
FROM sys.dm_db_partition_stats
WHERE object_id = OBJECT_ID('dbo.Movies');

Résultat :

+--------------------+-------------+
| partition_number   | row_count   |
|--------------------+-------------|
| 1                  | 1           |
| 2                  | 99          |
| 3                  | 900         |
| 4                  | 3079        |
+--------------------+-------------+

Nous pouvons voir comment les lignes sont réparties entre les partitions. Ils sont alloués exactement comme nous l'avons spécifié dans la fonction de partition. Les lignes totalisent 4 079, ce qui correspond exactement au nombre de lignes que nous avons insérées.

Cependant, il convient de noter que la documentation Microsoft indique en fait que cette colonne n'est qu'une approximative nombre de lignes dans chaque partition.

Meilleures pratiques

Microsoft recommande de toujours conserver des partitions vides aux deux extrémités de la plage de partitions.

C'est au cas où vous auriez besoin de diviser ou de fusionner les partitions à l'avenir.

La raison de cette recommandation est de garantir que la division et la fusion de la partition n'entraînent aucun mouvement de données inattendu.

Par conséquent, étant donné les données de mon exemple, je pourrais modifier la fonction de partition pour qu'elle ressemble à ceci :

CREATE PARTITION FUNCTION MoviesPartitionFunction (int)  
    AS RANGE LEFT FOR VALUES (-1, 100, 10000);
GO

Ou si j'anticipe plus de 10 000 lignes, je pourrais utiliser un plus grand nombre (ou créer plus de partitions).

Si je devais recréer toutes les étapes à nouveau, pour créer ma table partitionnée, mes statistiques de partition ressembleraient à ceci :

SELECT 
    partition_number,
    row_count
FROM sys.dm_db_partition_stats
WHERE object_id = OBJECT_ID('dbo.Movies');

Résultat :

+--------------------+-------------+
| partition_number   | row_count   |
|--------------------+-------------|
| 1                  | 0           |
| 2                  | 100         |
| 3                  | 3979        |
| 4                  | 0           |
+--------------------+-------------+

Maintenant, mes données sont concentrées dans les deux partitions du milieu et les partitions aux deux extrémités sont vides.