Секционирование таблиц SQL Server

В этом руководстве вы узнаете о секционировании таблиц SQL Server и о том, как создавать секционированные таблицы.

Введение в секционирование SQL Server

Секционирование таблиц позволяет хранить данные таблицы в нескольких физических разделах или секциях. Каждая секция имеет те же столбцы, но разный набор строк.

На практике вы используете секционирование таблиц для больших таблиц. Сделав это, вы получите следующие преимущества:

  • Более быстрое резервное копирование и обслуживание одного или нескольких разделов.
  • Передавайте или получайте доступ к подмножествам данных быстрее и эффективнее, сохраняя целостность всего набора данных.
  • Может улучшить производительность запросов.

Создание секционированной таблицы

Чтобы создать секционированную таблицу, выполните следующие действия:

  • Создайте группы файлов, содержащие разделы таблицы.
  • Создайте функцию секционирования, которая сопоставляет строки таблицы с секциями на основе значений указанного столбца.
  • Создайте схему разделов, которая сопоставляет таблицу разделов с новыми файловыми группами.
  • Создайте таблицу на основе схемы разбиения.

Мы будем использовать образец базы данных BikeStores для демонстрации. Следующий запрос возвращает сумму заказа по датам и продуктам:

WITH order_data(order_date, product_name, amount)
AS(
SELECT
  order_date,
  product_name,
  SUM(i.quantity * i.list_price *(1 - discount))
FROM sales.orders o
INNER JOIN sales.order_items i
  ON i.order_id = o.order_id
INNER JOIN production.products p
  ON p.product_id = i.product_id
GROUP BY order_date,
         product_name
)
SELECT * FROM order_data;

Выход:

Ниже приведена сводка заказов:

WITH order_data(order_date, product_name, amount)
AS(SELECT
  order_date,
  product_name,
  SUM(i.quantity * i.list_price *(1 - discount))
FROM sales.orders o
INNER JOIN sales.order_items i
  ON i.order_id = o.order_id
INNER JOIN production.products p
  ON p.product_id = i.product_id
GROUP BY order_date,
         product_name)
SELECT
  YEAR(order_date) year,
  COUNT(*) row_count
FROM order_data
GROUP BY YEAR(order_date);

Выход:

Мы создадим секционированную таблицу с именем sales.order_reports, которая будет хранить данные о заказах, возвращаемые вышеуказанным запросом. Таблица sales.order_reports будет иметь три секции. И каждая секция будет хранить строки, даты заказов которых будут в 2016, 2017 и 2018 годах.

1) Создание групп файлов

При создании базы данных SQL Server создает как минимум два файла: файл данных и файл журнала:

  • Файл данных содержит данные и объекты, такие как таблицы, индексы и представления.
  • Файл журнала содержит информацию для восстановления транзакций в базе данных.

SQL Server позволяет хранить данные в нескольких файлах данных и использует файловую группу для группировки файлов данных. По умолчанию файл данных принадлежит к ПЕРВИЧНОЙ файловой группе.

Чтобы добавить больше файловых групп в базу данных, используйте оператор ALTER DATABASE … ADD FILEGROUP.

Сначала добавьте три группы файлов в базу данных BikeStores:

ALTER DATABASE bikestores
ADD FILEGROUP orders_2016;
ALTER DATABASE bikestores
ADD FILEGROUP orders_2017;
ALTER DATABASE bikestores
ADD FILEGROUP orders_2018;

Во-вторых, проверьте файловые группы текущей базы данных, используя следующий оператор:

SELECT
  name
FROM sys.filegroups
WHERE type = 'FG';

Выход:

В-третьих, назначьте физические файлы файловым группам:

ALTER DATABASE bikestores    
ADD FILE    (
    NAME = orders_2016,
    FILENAME = 'D:\data\orders_2016.ndf',
        SIZE = 10 MB, 
        MAXSIZE = UNLIMITED, 
        FILEGROWTH = 1024 KB
    ) TO FILEGROUP orders_2016;
ALTER DATABASE bikestores    
ADD FILE    (
    NAME = orders_2017,
    FILENAME = 'D:\data\orders_2017.ndf',
        SIZE = 10 MB, 
        MAXSIZE = UNLIMITED, 
        FILEGROWTH = 1024 KB
    ) TO FILEGROUP orders_2017;
ALTER DATABASE bikestores    
ADD FILE    (
    NAME = orders_2018,
    FILENAME = 'D:\data\orders_2018.ndf',
        SIZE = 10 MB, 
        MAXSIZE = UNLIMITED, 
        FILEGROWTH = 1024 KB
    ) TO FILEGROUP orders_2018;

В этом примере мы назначаем три файла, расположенных в D:\data, файловым группам.

Наконец, проверьте назначение файловой группы с помощью следующего оператора:

SELECT 
 name as filename,
 physical_name as file_path
FROM sys.database_files
where type_desc = 'ROWS';

Выход:

2) Создать функцию разделения

Функция секционирования — это объект базы данных, который сопоставляет строки таблицы с секциями на основе значений указанного столбца. Этот столбец называется столбцом секционирования.

Функция секционирования принимает значения столбца секционирования и возвращает значение секционирования. Также она определяет количество секций и границы секций.

В нашем примере разделы будут основаны на значениях столбца order_date. И функция раздела создаст три раздела:

CREATE PARTITION FUNCTION order_by_year_function(date)
AS RANGE LEFT 
FOR VALUES('2016-12-31', '2017-12-31','2018-12-31');

В этом заявлении:

  • order_by_year_function — это имя функции разделения. Она принимает аргумент, тип данных которого — DATE.
  • AS RANGE LEFT FOR VALUES определяет три границы, в которых строки с датой до 31.12.2016 будут принадлежать разделу 1, строки с датой до 31.12.2017 и после 31.12.2016 будут принадлежать разделу 2, строки с датой между 31.12.2017 и 31.12.2018 будут принадлежать разделу 3.

3) Создание схемы разделов

Схема секционирования — это объект базы данных, который сопоставляет разделы, возвращаемые функцией секционирования, с файловыми группами.

Следующий оператор создает схему секционирования, которая сопоставляет секционирования, возвращаемые order_by_year_function, с файловыми группами:

CREATE PARTITION SCHEME order_by_year_scheme
AS PARTITION order_by_year_function
TO([orders_2016], [orders_2017], [orders_2018]);

4) Создание секционированной таблицы

Следующий оператор создает секционированную таблицу на основе схемы секционирования order_by_year_scheme:

CREATE TABLE sales.order_reports(
  order_date date,
  product_name varchar(255),
  amount decimal(10, 2) NOT NULL DEFAULT 0,
  PRIMARY KEY(order_date, product_name)
) 
ON order_by_year_scheme(order_date);

В этом заявлении:

  • Предложение ON order_by_year_scheme(order_date) определяет схему секционирования и столбец секционирования(order_date) для таблицы.
  • Столбец раздела должен быть включен в кластеризованный индекс, иначе возникнет ошибка.

Следующий оператор INSERT загружает данные в таблицу sales.order_reports:

INSERT INTO sales.order_reports(order_date, product_name, amount)
  SELECT
    order_date,
    product_name,
    SUM(i.quantity * i.list_price *(1 - discount))
  FROM sales.orders o
  INNER JOIN sales.order_items i
    ON i.order_id = o.order_id
  INNER JOIN production.products p
    ON p.product_id = i.product_id
  GROUP BY order_date,
           product_name;

Для проверки строк каждого раздела используйте следующий запрос:

SELECT 
 p.partition_number AS partition_number,
 f.name AS file_group, 
 p.rows AS row_count
FROM sys.partitions p
JOIN sys.destination_data_spaces dds ON p.partition_number = dds.destination_id
JOIN sys.filegroups f ON dds.data_space_id = f.data_space_id
WHERE OBJECT_NAME(OBJECT_ID) = 'order_reports'
order by partition_number;

Выход:

Краткое содержание

  • Используйте секционирование таблиц для хранения данных таблицы в нескольких физических разделах или секциях.
Мирослав С.

Автор статей, ИБ-специалист