F.46. pgpro_autopart — динамическое создание секций #
Расширение pgpro_autopart позволяет создавать секции динамически, то есть производит автоматическое секционирование при добавлении или изменении данных в таблице. Самый быстрый способ создания секций — вручную или по расписанию с помощью планировщика. Однако для некоторых задач скорость добавления данных не имеет большого значения. Для таких задач pgpro_autopart реализует автоматическое секционирование с помощью триггеров для представления секционированной таблицы.
F.46.1. Установка #
Расширение pgpro_autopart входит в состав Postgres Pro. Чтобы его задействовать, создайте расширение следующим запросом:
CREATE EXTENSION pgpro_autopart;
F.46.2. Использование #
Расширение pgpro_autopart использует для автоматического секционирования функцию ap_enable_automatic_partition_creation.
Примечание
Обратите внимание, что расширение работает только с новыми таблицами. Его нельзя использовать для существующих секционированных таблиц, поскольку оно не может отслеживать секции, которые были созданы пользователями ранее.
Сначала функция добавляет к имени указанной таблицы префикс real_, а затем создаёт представление с первоначальным именем таблицы и триггеры INSTEAD OF INSERT/UPDATE для этого представления.
Примечание
Обратите внимание, что администратор баз данных должен вручную предоставлять права на представление, созданное функцией ap_enable_automatic_partition_creation. Ожидается, что это будут те же права, что и для родительской таблицы.
Эти триггеры работают следующим образом:
INSTEAD OF INSERT: при попытке добавить запись в представление pgpro_autopart ищет секцию для этой записи. Если секция не найдена, она создаётся, после чего запись добавляется в секционированную таблицу.INSTEAD OF UPDATE: при попытке изменить запись в представлении pgpro_autopart ищет секцию для этой записи. Если секция не найдена, она создаётся, после чего запись изменяется в секционированной таблице.
Примечание
Оператор INSERT или UPDATE должен содержать значение ключа секционирования.
При использовании последовательности в качестве значения ключа необходимо явно задать это значение с помощью функции nextval(), поскольку опустить его нельзя. В противном случае операция INSERT или UPDATE завершится ошибкой.
В настоящее время поддерживаются только таблицы с секционированием по диапазону значения ключа (BY RANGE), которым должен быть один столбец типа date, timestamp, timestamptz, smallint, int или bigint.
При создании секций для ключа секционирования типа date/timestamp допустимыми значениями интервала являются year, quarter, month и day. То есть новая секция создаётся для каждого нового года, квартала, месяца или дня.
Имена новых секций следуют строго определённому формату: к имени секционированной таблицы добавляется суффикс, указывающий интервал, для которого создаётся секция. Например:
dayreal_t_day_2024_05_13для таблицыreal_t_daymonthreal_t_month_2024_05для таблицыreal_t_monthquarterreal_t_quarter_2024_2для таблицыreal_t_quarteryearreal_t_year_2025для таблицыreal_t_yearintreal_t_int_120_130для таблицыreal_t_intbigint"real_t_bigint_-60_-50"для таблицыreal_t_bigint
Триггеры INSTEAD OF INSERT/UPDATE проверяют наличие секции для каждой вставляемой или изменяемой записи, что может несколько замедлить работу.
Поскольку исходная секционированная таблица переименовывается, для продолжения работы непосредственно с этой таблицей следует добавлять префикс real_.
Важно
Помните, что максимальная длина имени таблицы в Postgres Pro — 63 байта. Когда расширение pgpro_autopart создаёт секцию, оно автоматически добавляет до 29 байт (префикс real_, два подчёркивания, символы границ) к имени таблицы для типа int и до 51 байта для ключа секционирования типа bigint. Ответственность за выбор соответствующих имён таблиц, чтобы избежать ошибок, лежит на пользователе.
F.46.3. Представление ap_tables_view #
Таблицы с включённым автоматическим секционированием показаны в представлении ap_tables_view. Ниже приведён пример данных в этом представлении.
SELECT * FROM ap_tables_view; apt_relname | apt_relschema | apt_mode -------------+---------------+----------------------------------------------------------------------------- t_month1 | user_schema | automatic partition creation with using triggers on VIEW (C-implementation) t_bigint1 | user_schema | automatic partition creation with using triggers on VIEW (C-implementation) (2 rows)
F.46.4. Функции #
-
ap_enable_automatic_partition_creation(a_relname text[, a_relschema text], a_interval text) returns void# Эта функция предназначена для таблиц с ключом секционирования типа
date,timestampилиtimestampz. Она переименовывает секционированную таблицуa_relname(схемыa_relschema), добавляя префиксreal_, а затем создаёт представление с тем же именем, что и у исходной таблицы, и добавляет для него триггерыINSTEAD OF INSERT/UPDATE. Эти триггеры при необходимости создают новую секцию, границы которой определяются интервалом, заданным в параметреa_interval(год, квартал, месяц, день).-
ap_enable_automatic_partition_creation(a_relname text[, a_relschema text], a_interval smallint, a_firstval smallint) returns void
ap_enable_automatic_partition_creation(a_relname text[, a_relschema text], a_interval int, a_firstval int) returns void
ap_enable_automatic_partition_creation(a_relname text[, a_relschema text], a_interval bigint, a_firstval bigint) returns void# Эти функции используются для таблиц с ключом секционирования типа
smallint,intилиbigint. Они переименовывают секционированную таблицуa_relname(схемыa_relschema), добавляя префиксreal_. Затем вызванная функция создаёт представление с тем же именем, что и у исходной таблицы, и триггерыINSTEAD OF INSERT/UPDATEдля него. Эти триггеры при необходимости создают новую секцию, границы которой определяются исходным значениемa_firstval, от которого отсчитываются интервалы, и значениемa_interval, определяющим длину интервала.-
ap_disable_automatic_partition_creation(a_relname text[, a_relschema text]) returns void# Функция удаляет триггеры, созданные функцией
ap_enable_automatic_partition_creationдля представления указанной секционированной таблицыa_relname(схемыa_relschema). Она также удаляет представление и переименовывает секционированную таблицу, убирая из её имени префиксreal_.
F.46.5. Пример #
В следующем примере показано использование расширения pgpro_autopart с ключом секционирования типа bigint.
Создайте расширение.
CREATE EXTENSION pgpro_autopart;
Создайте таблицу, секционированную с указанием BY RANGE с одностолбцовым ключом типа bigint.
CREATE TABLE t_bigint (b bigint, i int) PARTITION BY RANGE (b);
Используйте расширение, чтобы переименовать таблицу t_bigint в real_t_bigint, создать представление t_bigint для этой таблицы, а затем создать триггеры INSTEAD OF INSERT/UPDATE. Обратите внимание, что начальное значение для создания секций — 100, а секции создаются с интервалом 10 в обоих направлениях.
SELECT ap_enable_automatic_partition_creation('t_bigint', 10, 100);
ap_enable_automatic_partition_creation
----------------------------------------
(1 row)Добавьте две записи в таблицу. При добавлении первой записи будет автоматически создана секция real_t_bigint_110_120.
INSERT INTO t_bigint VALUES (111, 1); NOTICE: New partition "public"."real_t_bigint_110_120" created INSERT 0 1 INSERT INTO t_bigint VALUES (114, 2); INSERT 0 1
Измените у одной из записей поле ключа. При этом будет автоматически создана секция real_t_bigint_-60_-50.
UPDATE t_bigint SET b = -55 WHERE b = 114 RETURNING *; NOTICE: New partition "public"."real_t_bigint_-60_-50" created b | i -----+--- -55 | 2 (1 row) UPDATE 1
Проверьте секции таблицы real_t_bigint. Их должно быть две.
SELECT
c.oid::pg_catalog.regclass AS "name",
pg_catalog.pg_get_expr(c.relpartbound, c.oid) AS "condition"
FROM
pg_catalog.pg_class c,
pg_catalog.pg_inherits i
WHERE
c.oid = i.inhrelid AND i.inhparent = 'real_t_bigint'::regclass;
name | condition
-------------------------+------------------------------------
real_t_bigint_110_120 | FOR VALUES FROM ('110') TO ('120')
"real_t_bigint_-60_-50" | FOR VALUES FROM ('-60') TO ('-50')
(2 rows)Проверьте данные в таблице real_t_bigint и её секциях. В таблице должно быть две записи:
SELECT * FROM real_t_bigint; b | i -----+--- -55 | 2 111 | 1 (2 rows)
В секции real_t_bigint_110_120 должна быть одна запись:
SELECT * FROM real_t_bigint_110_120; b | i -----+--- 111 | 1 (1 row)
Также должна быть одна запись в секции real_t_bigint_-60_-50.
SELECT * FROM "real_t_bigint_-60_-50"; b | i -----+--- -55 | 2 (1 row)
Отключите триггеры, удалите представление и переименуйте таблицу real_t_bigint в t_bigint.
SELECT ap_disable_automatic_partition_creation('t_bigint');
ap_disable_automatic_partition_creation
-----------------------------------------
(1 row)Удалите таблицу и расширение.
DROP TABLE t_bigint; DROP TABLE DROP EXTENSION pgpro_autopart; DROP EXTENSION