Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Erstellen einer partitionierten Tabelle in SQL Server (T-SQL)

SQL Server unterstützt partitionierte Tabellen und Indizes. Wenn eine partitionierte Tabelle oder ein partitionierter Index partitioniert wird, werden ihre Daten in Einheiten unterteilt, die über mehr als eine Dateigruppe verteilt werden können.

Um eine partitionierte Tabelle in SQL Server zu erstellen, müssen Sie daher zuerst die Dateigruppe(n) erstellen, die jede Partition enthalten. Außerdem müssen Sie eine Partitionsfunktion und ein Partitionsschema erstellen.

Das geht also so:

  1. Dateigruppe(n) erstellen
  2. Erstellen Sie eine Partitionsfunktion
  3. Erstellen Sie ein Partitionsschema
  4. Erstellen Sie die partitionierte Tabelle

Nachfolgend finden Sie ein Beispiel für die Verwendung dieser Schritte zum Erstellen einer Tabelle mit vier Partitionen.

Dateigruppen erstellen

Zuerst fügen wir der Datenbank vier Dateigruppen mit dem Namen Test hinzu , und geben Sie dann die physische Datei für jede dieser Dateigruppen an.

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   

Sie müssen diesen Code je nach Ihren Anforderungen ändern. Sie müssen auch die Dateipfade an Ihre Umgebung anpassen. Unter Windows sieht Ihr Pfad beispielsweise eher wie D:\mssql\data\MoviesFg4dat.ndf aus .

Wenn Sie weitere Partitionen benötigen, fügen Sie hier weitere Dateigruppen hinzu. Wenn Sie hingegen weniger Partitionen benötigen, geben Sie hier weniger Dateigruppen an.

Erstellen Sie eine Partitionsfunktion

Als nächstes erstellen wir eine Partitionsfunktion namens MoviesPartitionFunction das wird die Tabelle in vier Partitionen partitionieren.

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

Der int part gibt den Datentyp der für die Partitionierung verwendeten Spalte an.

Alle Datentypen außer Text sind für die Verwendung als Partitionierungsspalten gültig , ntext , Bild , xml , Zeitstempel , varchar(max) , nvarchar(max) , varbinary(max) , Alias-Datentypen oder benutzerdefinierte CLR-Datentypen.

Hier verwende ich drei Grenzwerte (1, 100 , und 1000 ), um vier Partitionen anzugeben. Diese Grenzwerte müssen entweder mit dem in Klammern nach dem Namen der Partitionsfunktion angegebenen Datentyp übereinstimmen oder implizit in diesen konvertierbar sein.

Angesichts dieser Grenzwerte und der Tatsache, dass ich einen RANGE LEFT angegeben habe Partition enthalten die vier Partitionen die in der folgenden Tabelle angegebenen Werte.

Partition Werte
1 <= 1
2 1 UND <= 100
3 100 UND <=1000
4 1000

Wenn ich einen RANGE RIGHT angegeben hätte Partition, wäre die Aufschlüsselung etwas anders, wie in der folgenden Tabelle dargestellt.

Partition Werte
1 1
2 >= 1 UND < 100
3 >= 100 UND < 1000
4 >= 1000

Dasselbe Konzept gilt, wenn die Partitionierungsspalte andere Datentypen verwendet, z. B. Datums-/Uhrzeitwerte.

Erstellen Sie ein Partitionsschema

Als nächstes müssen wir ein Partitionsschema erstellen.

Ein Partitionsschema ordnet die Partitionen einer partitionierten Tabelle oder eines partitionierten Index den neuen Dateigruppen zu.

In unserem Fall sieht der Code so aus:

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

Beachten Sie, dass wir auf die Partitionsfunktion verweisen, die wir im vorherigen Schritt erstellt haben. Wir verweisen auch auf die Dateigruppen, die wir im ersten Schritt erstellt haben.

Erstellen Sie die partitionierte Tabelle

Schließlich können wir die partitionierte Tabelle erstellen.

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

Der einzige Unterschied zwischen diesem und dem Erstellen einer unpartitionierten Tabelle besteht darin, dass wir beim Erstellen einer partitionierten Tabelle den ON verwenden -Argument, um ein zu verwendendes Partitionsschema anzugeben. In unserem Fall geben wir das Partitionsschema an, das wir im vorherigen Schritt erstellt haben, und geben die MovieId an Spalte als Partitionierungsspalte.

Sie werden feststellen, dass die MovieId Spalte hat den Datentyp int , was den Grenzwerten entspricht, die wir beim Erstellen der Partitionsfunktion angegeben haben.

Beachten Sie, dass, wenn Sie eine berechnete Spalte in einer Partitionsfunktion verwenden, diese ausdrücklich als PERSISTED gekennzeichnet werden muss .

Prüfen Sie die Partitionsfunktion

Sie können die sys.partition_functions verwenden view, um alle Partitionsfunktionen zurückzugeben.

SELECT * FROM sys.partition_functions; 

Ergebnis (bei vertikaler Ausgabe):

| MoviesPartitionFunctionfunction_id | 65536Typ | R type_desc | BEREICHfanout | 4boundary_value_on_right | 0ist_system | 0create_date | 10.10.2020 05:37:41.330modify_date | 10.10.2020 05:37:41.330

Prüfen Sie das Partitionsschema

Sie können sys.partition_schemes verwenden um das Partitionsschema zu überprüfen.

SELECT * FROM sys.partition_schemes; 

Ergebnis (bei vertikaler Ausgabe):

| MoviesPartitionSchemedata_space_id | 65601typ | PStype_desc | PARTITION_SCHEMEis_default | 0ist_system | 0Funktions-ID | 65536

Alternativ können Sie die folgende Abfrage verwenden, um andere Details wie Schema, Tabelle, Index usw. zurückzugeben.

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; 

Ergebnis (bei vertikaler Ausgabe):

Schema | dboObject | FilmeIndex | PK__Movies__4BD2941A0ED85ACAPartitionsschema | MoviesPartitionScheme

Prüfen Sie die partitionierte Tabelle

Sie können sys.dm_db_partition_stats ausführen view, um Seiten- und Zeilenanzahlinformationen für jede Partition in der aktuellen Datenbank zurückzugeben.

Aber wenn Sie das ausführen, bevor Sie irgendwelche Daten in die Tabelle einfügen, werden die meisten Statistiken Null sein.

Also werde ich zuerst Daten einfügen.

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

Ergebnis:

(4079 Zeilen betroffen)

Wir können sehen, dass 4.079 Zeilen eingefügt wurden.

Lassen Sie uns nun die sys.dm_db_partition_stats abfragen ansehen.

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

Ergebnis:

+--------------+------------+------------ +--------------------+---------------------+- ---------------------+------------------------ ------+---------------+-------------- --------+-------------------------------+-------- -----------------------+-------------------+- ----------------------+-------------+| partition_id | Objekt-ID | index_id | Partitionsnummer | 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 | reservierte_seitenzahl | Zeilenanzahl ||------+------------+------------+ --------------------+-------------------------+-- ------------------------+-------------------- -----+-----------------------+-------------------- ------+--------------------------------+--------- ----------------------------+-------------------+-- ---------------------+-------------|| 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 |+--------------+------------+------------+ --------------------+-------------------------+-- ------------------------+-------------------- -----+-----------------------+-------------------- ------+--------------------------------+--------- ----------------------------+-------------------+-- ---------------------+-------------+

Diese Ansicht gibt viele Spalten zurück, also grenzen wir die Spalten auf ein paar ein.

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

Ergebnis:

+--------------------+---------------------+| Partitionsnummer | Zeilenanzahl ||--------------------+---------------------|| 1 | 1 || 2 | 99 || 3 | 900 || 4 | 3079 |+--------------------+---------------------+

Wir können sehen, wie die Zeilen über die Partitionen verteilt sind. Sie werden genau so zugewiesen, wie wir es in der Partitionsfunktion angegeben haben. Die Zeilen umfassen insgesamt 4.079, genau so viele Zeilen haben wir eingefügt.

Es ist jedoch erwähnenswert, dass die Microsoft-Dokumentation tatsächlich besagt, dass diese Spalte nur ein ungefährer Wert ist Anzahl der Zeilen in jeder Partition.

Best Practice

Microsoft empfiehlt, immer leere Partitionen an beiden Enden des Partitionsbereichs beizubehalten.

Dies ist für den Fall, dass Sie die Partitionen in Zukunft entweder aufteilen oder zusammenführen müssen.

Der Grund für diese Empfehlung besteht darin, sicherzustellen, dass die Partitionsteilung und die Partitionszusammenführung keine unerwarteten Datenverschiebungen nach sich ziehen.

Angesichts der Daten in meinem Beispiel könnte ich daher die Partitionsfunktion so ändern, dass sie etwa so aussieht:

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

Oder wenn ich mit mehr als 10.000 Zeilen rechne, könnte ich eine größere Zahl verwenden (oder mehr Partitionen erstellen).

Wenn ich alle Schritte erneut erstellen würde, um meine partitionierte Tabelle zu erstellen, würden meine Partitionsstatistiken wie folgt aussehen:

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

Ergebnis:

+--------------------+---------------------+| Partitionsnummer | Zeilenanzahl ||--------------------+---------------------|| 1 | 0 || 2 | 100 || 3 | 3979 || 4 | 0 |+--------------------+-------------+

Jetzt sind meine Daten in den mittleren zwei Partitionen konzentriert und die Partitionen an beiden Enden sind leer.