SQL Server obsługuje partycjonowane tabele i indeksy. Kiedy podzielona na partycje tabela lub indeks jest podzielony na partycje, jego dane są dzielone na jednostki, które mogą być rozłożone na więcej niż jedną grupę plików.
Dlatego, aby utworzyć partycjonowaną tabelę w SQL Server, musisz najpierw utworzyć grupy plików, które będą przechowywać każdą partycję. Musisz również utworzyć funkcję partycji i schemat partycji.
A więc wygląda to tak:
- Utwórz grupę/grupy plików
- Utwórz funkcję partycji
- Utwórz schemat partycji
- Utwórz tabelę podzieloną na partycje
Poniżej znajduje się przykład wykorzystania tych kroków do utworzenia tabeli z czterema partycjami.
Utwórz grupy plików
Najpierw dodajemy cztery grupy plików do bazy danych o nazwie Test , a następnie określ plik fizyczny dla każdej z tych grup plików.
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
Będziesz musiał zmienić ten kod, w zależności od Twoich wymagań. Będziesz także musiał zmienić ścieżki plików, aby dopasować je do swojego środowiska. Na przykład, jeśli korzystasz z systemu Windows, ścieżka może wyglądać bardziej jak D:\mssql\data\MoviesFg4dat.ndf
.
Ponadto, jeśli potrzebujesz więcej partycji, dodaj więcej grup plików tutaj. I odwrotnie, jeśli potrzebujesz mniej partycji, określ tutaj mniej grup plików.
Utwórz funkcję partycji
Następnie tworzymy funkcję partycji o nazwie MoviesPartitionFunction który podzieli tabelę na cztery partycje.
CREATE PARTITION FUNCTION MoviesPartitionFunction (int)
AS RANGE LEFT FOR VALUES (1, 100, 1000);
GO
int część określa typ danych kolumny używanej do partycjonowania.
Wszystkie typy danych mogą być używane jako kolumny partycjonujące, z wyjątkiem tekstu , ntekst , obraz , xml , sygnatura czasowa , varchar(maks.) , nvarchar(maks.) , zmienna (maks.) , typy danych aliasów lub typy danych zdefiniowane przez użytkownika CLR.
Tutaj używam trzech wartości granicznych (1, 100
i 1000
), aby określić cztery partycje. Te wartości graniczne muszą być zgodne lub niejawnie konwertowane na typ danych określony w nawiasach po nazwie funkcji partycji.
Biorąc pod uwagę te wartości graniczne oraz fakt, że określiłem RANGE LEFT
partycji, cztery partycje będą przechowywać wartości określone w poniższej tabeli.
Partycja | Wartości |
---|---|
1 | <= 1 |
2 | > 1 ORAZ <= 100 |
3 | > 100 ORAZ <=1000 |
4 | > 1000 |
Gdybym określił RANGE RIGHT
partycji, podział byłby nieco inny, jak przedstawiono w poniższej tabeli.
Partycja | Wartości |
---|---|
1 | < 1 |
2 | >= 1 ORAZ < 100 |
3 | >= 100 ORAZ < 1000 |
4 | >= 1000 |
Ta sama koncepcja ma zastosowanie, jeśli kolumna partycjonowania używa innych typów danych, takich jak wartości daty/godziny.
Utwórz schemat partycji
Następnie musimy stworzyć schemat partycji.
Schemat partycji mapuje partycje z partycjonowanej tabeli lub indeksu do nowych grup plików.
W naszym przypadku kod będzie wyglądał tak:
CREATE PARTITION SCHEME MoviesPartitionScheme
AS PARTITION MoviesPartitionFunction
TO (MoviesFg1, MoviesFg2, MoviesFg3, MoviesFg4);
GO
Zauważ, że odwołujemy się do funkcji partycji, którą utworzyliśmy w poprzednim kroku. Odwołujemy się również do grup plików, które utworzyliśmy w pierwszym kroku.
Utwórz tabelę partycjonowaną
Wreszcie możemy utworzyć tabelę podzieloną na partycje.
CREATE TABLE Movies (
MovieId int IDENTITY PRIMARY KEY,
MovieName varchar(60)
)
ON MoviesPartitionScheme (MovieId);
GO
Jedyną różnicą między tym a tworzeniem tabeli bez partycji jest to, że podczas tworzenia tabeli partycjonowanej używamy ON
argument, aby określić schemat partycji do użycia. W naszym przypadku określamy schemat partycji, który utworzyliśmy w poprzednim kroku, i określamy MovieId kolumna jako kolumna partycjonująca.
Zauważysz, że MovieId kolumna ma typ danych int , który pasuje do wartości granicznych, które określiliśmy podczas tworzenia funkcji partycji.
Pamiętaj, że jeśli używasz kolumny wyliczanej w funkcji partycji, musi być ona jawnie oznaczona jako PERSISTED
.
Sprawdź funkcję partycji
Możesz użyć sys.partition_functions
widok, aby zwrócić wszystkie funkcje partycji.
SELECT * FROM sys.partition_functions;
Wynik (przy użyciu wyjścia pionowego):
nazwa | MoviesPartitionFunctionfunction_id | 65536typ | R type_desc | RANGEfanout | 4boundary_value_on_right | 0is_system | 0data_utworzenia | 2020-10-10 05:37:41.330modify_date | 2020-10-10 05:37:41.330
Sprawdź schemat partycji
Możesz użyć sys.partition_schemes
aby sprawdzić schemat partycji.
SELECT * FROM sys.partition_schemes;
Wynik (przy użyciu wyjścia pionowego):
nazwa | MoviesPartitionSchemedata_space_id | 65601typ | PStype_desc | PARTITION_SCHEMEjest_domyślny | 0is_system | 0 identyfikator_funkcji | 65536
Alternatywnie możesz użyć następującego zapytania, aby zwrócić inne szczegóły, takie jak schemat, tabela, indeks itp.
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;
Wynik (przy użyciu wyjścia pionowego):
Schemat | dboObject | Indeks filmów | PK__Movies__4BD2941A0ED85ACASchemat podziału | MoviesPartitionScheme
Sprawdź tabelę partycjonowaną
Możesz uruchomić sys.dm_db_partition_stats
zobacz, aby zwrócić informacje o stronie i liczbie wierszy dla każdej partycji w bieżącej bazie danych.
Ale uruchomienie tego przed wstawieniem jakichkolwiek danych do tabeli spowoduje, że większość statystyk będzie wynosić zero.
Więc najpierw wstawię dane.
INSERT INTO Movies
SELECT name FROM OtherDb.dbo.Movies;
Wynik:
(4079 wierszy dotyczy)
Widzimy, że wstawiono 4079 wierszy.
Teraz zapytajmy sys.dm_db_partition_stats
widok.
SELECT *
FROM sys.dm_db_partition_stats
WHERE object_id = OBJECT_ID('dbo.Movies');
Wynik:
+--------------------+--------------+---------------- +---------------------+--------------------------+- -------------------------+------------------------ -------+------------------------+------------------- --------+--------------------------------+-------- ----------------------------+-------------------+- ------------+-------------+| partycja_id | identyfikator_obiektu | index_id | numer_partycji | 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 | liczba_wierszów ||-------------------+-------------+----------------+ ---------+-------------------------------------+-- --------------+----------------------------------------- --+------------------------+------------------------- -------+---------------------+--------- ----------------------------+-------------------+-- ---------------------+--------------|| 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 |+--------------------+--------------+-------------+ ---------+-------------------------------------+-- --------------+----------------------------------------- --+------------------------+------------------------- -------+---------------------+--------- ----------------------------+-------------------+-- ---------------------+-------------+
Ten widok zwraca wiele kolumn, więc zawęźmy kolumny do zaledwie kilku.
SELECT
partition_number,
row_count
FROM sys.dm_db_partition_stats
WHERE object_id = OBJECT_ID('dbo.Movies');
Wynik:
+---------------------+--------------+| numer_partycji | liczba_wierszów ||--------------------+-------------||| 1 | 1 || 2 | 99 || 3 | 900 || 4 | 3079 |+---------------------+-------------+
Możemy zobaczyć, jak wiersze są alokowane w partycjach. Są alokowane dokładnie tak, jak określiliśmy w funkcji partycji. Liczba wierszy wynosi 4079, czyli dokładnie tyle, ile wstawiliśmy.
Warto jednak zauważyć, że dokumentacja Microsoftu faktycznie stwierdza, że ta kolumna jest tylko przybliżona liczba wierszy w każdej partycji.
Najlepsza praktyka
Microsoft zaleca, abyśmy zawsze trzymali puste partycje na obu końcach zakresu partycji.
Dzieje się tak na wypadek, gdyby w przyszłości trzeba było podzielić lub scalić partycje.
Powodem tego zalecenia jest zagwarantowanie, że podział partycji i scalenie partycji nie pociągnie za sobą żadnego nieoczekiwanego przeniesienia danych.
Dlatego biorąc pod uwagę dane z mojego przykładu, mogę zmienić funkcję partycji, aby wyglądała mniej więcej tak:
CREATE PARTITION FUNCTION MoviesPartitionFunction (int)
AS RANGE LEFT FOR VALUES (-1, 100, 10000);
GO
Lub jeśli spodziewam się więcej niż 10 000 wierszy, mogę użyć większej liczby (lub utworzyć więcej partycji).
Gdybym miał ponownie odtworzyć wszystkie kroki, aby utworzyć tabelę podzieloną na partycje, moje statystyki partycji wyglądałyby tak:
SELECT
partition_number,
row_count
FROM sys.dm_db_partition_stats
WHERE object_id = OBJECT_ID('dbo.Movies');
Wynik:
+---------------------+--------------+| numer_partycji | liczba_wierszów ||--------------------+-------------||| 1 | 0 || 2 | 100 || 3 | 3979 || 4 | 0 |+---------------------+-------------+
Teraz moje dane są skoncentrowane na dwóch środkowych partycjach, a partycje na obu końcach są puste.