SQL Server поддържа разделени таблици и индекси. Когато една разделена таблица или индекс е разделена, нейните данни се разделят на единици, които могат да бъдат разпределени в повече от една файлова група.
Следователно, за да създадете разделена таблица в SQL Server, първо трябва да създадете файловата група/и, които ще съдържат всеки дял. Също така трябва да създадете функция за дялове и схема на дялове.
Така че става така:
- Създайте файлова група/и
- Създайте функция за разделяне
- Създайте схема на дялове
- Създайте разделената таблица
По-долу е даден пример за използване на тези стъпки за създаване на таблица с четири дяла.
Създаване на файлови групи
Първо добавяме четири файлови групи към базата данни, наречена Тест и след това посочете физическия файл за всяка от тези файлови групи.
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
Ще трябва да промените този код в зависимост от вашите изисквания. Ще трябва също да промените пътеките на файловете, за да отговарят на вашата среда. Например, ако сте на Windows, пътят ви може да изглежда по-скоро като D:\mssql\data\MoviesFg4dat.ndf
.
Освен това, ако имате нужда от повече дялове, добавете още файлови групи тук. Обратно, ако имате нужда от по-малко дялове, посочете тук по-малко файлови групи.
Създаване на функция за дял
След това създаваме функция за дял, наречена MoviesPartitionFunction което ще раздели таблицата на четири дяла.
CREATE PARTITION FUNCTION MoviesPartitionFunction (int)
AS RANGE LEFT FOR VALUES (1, 100, 1000);
GO
Винт part определя типа данни на колоната, използвана за разделяне.
Всички типове данни са валидни за използване като колони за разделяне, с изключение на текст , ntext ,изображение , xml , клеймо за време , varchar(max) , nvarchar(max) ,варбинарна(макс.) , псевдоними типове данни или CLR потребителски дефинирани типове данни.
Тук използвам три гранични стойности (1, 100
и 1000
), за да посочите четири дяла. Тези гранични стойности трябва или да съвпадат, или да бъдат имплицитно конвертируеми в типа данни, посочен в скоби след името на функцията за дял.
Предвид тези гранични стойности и факта, че посочих RANGE LEFT
дял, четирите дяла ще задържат стойности, както е посочено в следващата таблица.
Дял | Стойности |
---|---|
1 | <= 1 |
2 | > 1 И <= 100 |
3 | > 100 И <=1000 |
4 | > 1000 |
Ако бях посочил RANGE RIGHT
дял, разбивката ще бъде малко по-различна, както е посочено в следващата таблица.
Дял | Стойности |
---|---|
1 | < 1 |
2 | >= 1 И < 100 |
3 | >= 100 И < 1000 |
4 | >= 1000 |
Същата концепция се прилага, ако колоната за разделяне използва други типове данни, като стойности за дата/час.
Създайте схема на дялове
След това трябва да създадем схема на дялове.
Схемата на дяловете съпоставя дяловете на разделена таблица или индекс към новите файлови групи.
В нашия случай кодът ще изглежда така:
CREATE PARTITION SCHEME MoviesPartitionScheme
AS PARTITION MoviesPartitionFunction
TO (MoviesFg1, MoviesFg2, MoviesFg3, MoviesFg4);
GO
Забележете, че се позоваваме на функцията за дял, която създадохме в предишната стъпка. Също така препращаме към файловите групи, които създадохме в първата стъпка.
Създайте разделената таблица
Накрая можем да създадем разделената таблица.
CREATE TABLE Movies (
MovieId int IDENTITY PRIMARY KEY,
MovieName varchar(60)
)
ON MoviesPartitionScheme (MovieId);
GO
Единствената разлика между това и създаването на неразделена таблица е, че когато създаваме разделена таблица, ние използваме ON
аргумент за определяне на схема на дялове, която да се използва. В нашия случай указваме схемата на дялове, която създадохме в предишната стъпка, и задаваме MovieId колона като разделителна колона.
Ще забележите, че MovieId колоната има тип данни int , което съответства на граничните стойности, които сме посочили при създаването на функцията за дял.
Обърнете внимание, че ако използвате изчислена колона във функция на дял, тя трябва да бъде изрично маркирана PERSISTED
.
Проверете функцията за разделяне
Можете да използвате sys.partition_functions
преглед, за да върнете всички функции на дялове.
SELECT * FROM sys.partition_functions;
Резултат (с помощта на вертикален изход):
<предварително име | MoviesPartitionFunctionfunction_id | 65536 тип | R type_desc | RANGEfanout | 4boundary_value_on_right | 0is_system | 0create_date | 2020-10-10 05:37:41.330modify_date | 2020-10-10 05:37:41,330Проверете схемата на дяловете
Можете да използвате sys.partition_schemes
за да проверите схемата на дяловете.
SELECT * FROM sys.partition_schemes;
Резултат (с помощта на вертикален изход):
<предварително име | MoviesPartitionSchemedata_space_id | 65601 тип | PStype_desc | PARTITION_SCHEME е_по подразбиране | 0is_system | 0function_id | 65536Като алтернатива можете да използвате следната заявка, за да върнете други подробности, като схема, таблица, индекс и др.
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;
Резултат (с помощта на вертикален изход):
<предварителна>Схема | dboObject | Индекс на филми | PK__Movies__4BD2941A0ED85ACA Схема на дялове | Схема за разделяне на филмиПроверете разделената таблица
Можете да стартирате sys.dm_db_partition_stats
преглед за връщане на информация за страница и брой редове за всеки дял в текущата база данни.
Но изпълнението на това преди вмъкване на каквито и да е данни в таблицата ще доведе до това, че повечето статистически данни са нулеви.
Така че първо ще вмъкна данни.
INSERT INTO Movies
SELECT name FROM OtherDb.dbo.Movies;
Резултат:
(засегнати 4079 реда)
Виждаме, че бяха вмъкнати 4079 реда.
Сега нека да запитаме sys.dm_db_partition_stats
изглед.
SELECT *
FROM sys.dm_db_partition_stats
WHERE object_id = OBJECT_ID('dbo.Movies');
Резултат:
+------------------+------------+------------ +-------------------+---------------------+- -------------------------+----------------------- ------+-----------------------+------------------- --------+--------------------------------+-------- ----------------------------+-------------------+- ---------------------+------------+| partition_id | обект_идентификатор | идентификатор_индекс | номер_на дял | 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 | използвани_брой_страници | запазени_брой_страници | брой_редове ||-------------------+------------+------------+ --------------------+--------------------------+-- ------------------------+-------------------------------- -----+-----------------------+-------------------- -------+--------------------------------+-------- ---------------------------+-------------------+-- ---------------------+------------|| 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 |+-------------------+------------+-----------+ --------------------+--------------------------+-- ------------------------+-------------------------------- -----+-----------------------+-------------------- -------+--------------------------------+-------- ---------------------------+-------------------+-- ---------------------+------------+
Този изглед връща много колони, така че нека стесним колоните само до няколко.
SELECT
partition_number,
row_count
FROM sys.dm_db_partition_stats
WHERE object_id = OBJECT_ID('dbo.Movies');
Резултат:
+--------------------+------------+| номер_на дял | брой_редове ||-------------------+------------|| 1 | 1 || 2 | 99 || 3 | 900 || 4 | 3079 |+-------------------+------------+
Можем да видим как редовете са разпределени в дяловете. Те са разпределени точно както сме посочили във функцията за дял. Общо редовете са 4079, което е точно колко реда вмъкнахме.
Въпреки това си струва да се отбележи, че документацията на Microsoft всъщност посочва, че тази колона е само приблизителна броят на редовете във всеки дял.
Най-добра практика
Microsoft препоръчва винаги да съхраняваме празни дялове в двата края на диапазона от дялове.
Това е в случай, че трябва или да разделите, или да обедините дяловете в бъдеще.
Причината за тази препоръка е да се гарантира, че разделянето на дяла и сливането на дяла няма да предизвикат неочаквано движение на данни.
Следователно, като се имат предвид данните в моя пример, бих могъл да променя функцията за дялове, за да изглежда така:
CREATE PARTITION FUNCTION MoviesPartitionFunction (int)
AS RANGE LEFT FOR VALUES (-1, 100, 10000);
GO
Или ако очаквам повече от 10 000 реда, бих могъл да използвам по-голям брой (или да създам повече дялове).
Ако трябваше да пресъздам всички стъпки отново, за да създам моята разделена таблица, статистиката на моя дял ще изглежда така:
SELECT
partition_number,
row_count
FROM sys.dm_db_partition_stats
WHERE object_id = OBJECT_ID('dbo.Movies');
Резултат:
+--------------------+------------+| номер_ на дял | брой_редове ||-------------------+------------|| 1 | 0 || 2 | 100 || 3 | 3979 || 4 | 0 |+-------------------+------------+
Сега данните ми са концентрирани в средните два дяла, а дяловете в двата края са празни.