Партиционирование: классический синтаксис
Партиционирование (или секционирование) помогает эффективно работать с очень большими таблицами, например таблицами фактов, разбивая их на меньшие части — партиции (секции). Это позволяет ускорить выполнение запросов, поскольку оптимизатор Greengage DB обращается только к нужным партициям, а не ко всей таблице.
Настройки партиционирования указываются при создании таблицы с помощью ключа партиционирования — одного или нескольких столбцов, по которым определяется, как данные распределяются по партициям.
Начиная с Greengage DB 7 также поддерживается декларативный синтаксис партиционирования, унаследованный от PostgreSQL. Декларативное партиционирование рекомендуется использовать для новых партиционированных таблиц, поскольку оно обеспечивает большую гибкость. Подробнее см. в разделе Партиционирование.
Введение в партиционирование таблиц
Как работает партиционирование
Партиционирование и распределение данных выполняют разные задачи в Greengage DB. Партиционирование делит большую таблицу на меньшие части для повышения производительности запросов и упрощения обслуживания, например, архивирования или удаления устаревших данных. Распределение, в свою очередь, определяет, как данные (и в партиционированных, и в непартиционированных таблицах) распределяются по сегментам для обеспечения параллельного выполнения запросов. Партиционирование не влияет на распределение данных по сегментам.
Таблицы разбиваются на партиции при создании с помощью выражения PARTITION BY, при необходимости с последующим указанием SUBPARTITION BY для многоуровневого партиционирования.
Партиционирование создает родительскую таблицу с одним или несколькими уровнями дочерних таблиц.
Между родительской и дочерними таблицами устанавливается отношение наследования, схожее по функциональности с выражением INHERITS.
Greengage DB использует критерии партиционирования, определенные при создании таблицы, чтобы создавать отдельные партиции.
Каждая партиция создается с ограничением-проверкой (CHECK), которое определяет допустимый диапазон данных для этой партиции.
Оптимизатор запросов использует эти ограничения, чтобы понять, какие партиции нужно просканировать для выполнения запроса с заданным условием.
Данный пример показывает таблицу sales с одноуровневым партиционированием, где каждая партиция охватывает один месяц в первом квартале 2025 года.
Каждая партиция соответствует определенному диапазону дат, заданному правилами партиционирования:
sales ├─── sales_1_prt_jan_2025 (date >= '2025-01-01' AND date < '2025-02-01') ├─── sales_1_prt_feb_2025 (date >= '2025-02-01' AND date < '2025-03-01') └─── sales_1_prt_mar_2025 (date >= '2025-03-01' AND date < '2025-04-01')
В следующем примере показана таблица sales с двухуровневым партиционированием.
Ежемесячные партиции дополнительно разбиваются на сабпартиции по столбцу region, разделяя данные на сабпартиции asia и europe:
sales
├─── sales_1_prt_jan_2025 (date >= '2025-01-01' AND date < '2025-02-01')
│ ├─── sales_1_prt_jan_2025_2_prt_asia (region = 'Asia')
│ └─── sales_1_prt_jan_2025_2_prt_europe (region = 'Europe')
├─── sales_1_prt_feb_2025 (date >= '2025-02-01' AND date < '2025-03-01')
│ ├─── sales_1_prt_feb_2025_2_prt_asia (region = 'Asia')
│ └─── sales_1_prt_feb_2025_2_prt_europe (region = 'Europe')
└─── sales_1_prt_mar_2025 (date >= '2025-03-01' AND date < '2025-04-01')
├─── sales_1_prt_mar_2025_2_prt_asia (region = 'Asia')
└─── sales_1_prt_mar_2025_2_prt_europe (region = 'Europe')
Для вставки данных в партиционированную таблицу обычно используется либо родительская партиционированная таблица (sales в приведенном выше примере), либо одна из ее листовых дочерних партиций (например, sales_1_prt_jan_2025_2_prt_asia и sales_1_prt_jan_2025_2_prt_europe).
При вставке данных учитывайте следующее:
-
Вы можете вставлять данные в родительскую таблицу (например,
sales), созданную с помощью командыCREATE TABLE. Greengage DB автоматически распределяет данные по дочерним партициям на основе правил партиционирования. -
Вы можете вставлять данные напрямую в партицию нижнего уровня (например,
sales_1_prt_jan_2025_2_prt_europe), если данные соответствуют критериям этой партиции. -
Вставка данных в промежуточную партицию (например,
sales_1_prt_jan_2025) не поддерживается и приведет к ошибке.
Обратите внимание, что верхнеуровневые и промежуточные таблицы — например, sales, sales_1_prt_jan_2025, sales_1_prt_feb_2025 и sales_1_prt_mar_2025 — остаются пустыми после вставки данных.
Рекомендуемая практика загрузки данных в партиционированные таблицы — использование обмена партиции.
Когда использовать партиционирование
Используйте партиционирование, если к таблице применимы большинство из следующих пунктов:
-
Таблица представляет собой большую таблицу фактов.
Таблицы фактов с миллионами строк хорошо подходят для партиционирования. Партиционирование небольших таблиц с тысячами строк и меньше, напротив, малоэффективно.
-
Вас не устраивает текущая скорость выполнения запросов к данным.
Применяйте партиционирование только к тем таблицам, запросы к которым выполняются значительно медленнее, чем требуется.
-
Существует столбец, позволяющий разделить таблицу на примерно равные по размеру партиции.
Выберите ключ для партиционирования, чтобы количество строк в каждой партиции было приблизительно одинаковым. Чем равномернее таблица разбита на небольшие части, тем выше будет прирост производительности за счет партиционирования. Например, разделение таблицы на 10 партиций одинакового размера может увеличить производительность запросов до 10 раз — при условии, что ключ партиционирования используется в предикатах запроса (см. следующий пункт ниже).
-
Большинство запросов, требующих ускорения, используют ключ партиционирования в своих условиях.
Партиционирование повышает производительность только тогда, когда оптимизатор может отфильтровать партиции на основе предикатов запроса. Если запрос сканирует все партиции, его выполнение может быть медленнее, чем при работе с непартиционированной таблицей. Убедитесь, что планы выполнения запросов содержат partition elimination (сканирование ограниченного числа партиций).
-
Существуют бизнес-требования по хранению исторических данных.
Партиционирование хорошо подходит для управления хранением данных по периодам времени. Например, если нужно хранить данные только за последние 12 месяцев, можно удалить самую старую партицию и загрузить новые данные в новую партицию.
Избегайте создания большего числа партиций, чем необходимо. Чрезмерное партиционирование может негативно сказаться на работе системы, включая операции вакуумирования, восстановление сегментов, расширение кластера, проверку использования диска и другие операции.
Обзор синтаксиса
Чтобы задать стратегию партиционирования, используйте выражение PARTITION BY в команде CREATE TABLE.
Чтобы партиционировать таблицу:
-
Определите схему партиционирования: по временному диапазону, числовому диапазону или списку значений.
-
Выберите столбец (или столбцы), который будет использоваться в качестве ключа партиционирования.
-
Определите необходимое количество уровней партиционирования. Например, можно создать таблицу с партиционированием по месяцам, а затем разбить каждую месячную партицию на сабпартиции по региону продаж.
Упрощенный синтаксис команды CREATE TABLE с одноуровневым партиционированием выглядит следующим образом:
CREATE TABLE <table_name> (
<column_definitions>
)
[ PARTITION BY <partition_type> (<column>)
(
<partition_spec>
)]
Основные аргументы:
-
partition_type— указывает тип партиционирования:LIST(на основе списка значений) илиRANGE(на основе диапазона: числового или дат). -
column— определяет столбец, используемый для партиционирования. -
partition_spec— определяет создаваемые партиции. Основные выражения:-
START,ENDиEVERY— используются для определения партиций на основе диапазонов. -
VALUES— указывает значения для партиций на основе списков значений. -
DEFAULT PARTITION— служит для размещения строк, не соответствующих заданным условиям; применяется ко всем типам партиционирования. Обратите внимание, что оптимизатор запросов всегда сканирует партицию по умолчанию, что может замедлить общее время сканирования, если эта партиция содержит данные.
-
Партиционирование на основе диапазонов
Партиционирование по диапазону делит данные на основе числовых или временных диапазонов.
Используйте выражение PARTITION BY RANGE, чтобы указать столбец ключа партиционирования, а затем определите интервалы партиций с помощью ключевых слов START и END.
Модификаторы INCLUSIVE и EXCLUSIVE определяют, включаются ли граничные значения в диапазон.
По умолчанию значения START включаются в диапазон, а значения END — исключаются.
Существует два способа определить партиции на основе диапазонов — автоматически и вручную.
Автоматическое формирование партиций
Чтобы создать партиции автоматически, используйте выражения START и END для указания границ общего диапазона.
Затем укажите размер партиции с помощью выражения EVERY:
-
Для временных диапазонов необходимо указать единицу интервала, например,
day,monthилиyear. Пример:EVERY (INTERVAL '1 month'). -
Для числовых диапазонов указывается значение шага. Пример:
EVERY (100).
Greengage DB автоматически создает необходимые партиции, деля весь диапазон на равные интервалы на основании указанного шага.
PARTITION BY RANGE (<column>)
(
START ([<datatype>] '<start_value>') [INCLUSIVE | EXCLUSIVE]
END ([<datatype>] '<end_value>') [INCLUSIVE | EXCLUSIVE] ]
EVERY ([<datatype>] [<number> | INTERVAL] '<interval_value>') ]
);
Определение партиций вручную
Альтернативный способ задания партиционированной таблицы — указание каждой партиции вручную.
В этом случае перечислите определения партиций через запятую в скобках после выражения PARTITION BY RANGE.
Определение каждой партиции начинается с выражения PARTITION <partition_name>, где <partition_name> — пользовательский идентификатор, который используется в имени партиции вместо автоматически сгенерированного числа.
После имени партиции используйте стандартные выражения START и END для задания границ диапазона каждой партиции.
Обратите внимание, что только для последней партиции необходимо указывать значение END; для всех остальных оно необязательно.
PARTITION BY RANGE (<column>)
(
PARTITION <partition_name>
START ([<datatype>] '<start_value>') [INCLUSIVE | EXCLUSIVE]
END ([<datatype>] '<end_value>') [INCLUSIVE | EXCLUSIVE],
[PARTITION <partition_name> ...]
);
Партиционирование на основе списков значений
Партиционирование на основе списков значений делит данные на основе заранее определенного набора значений ключа партиционирования.
Используйте выражение PARTITION BY LIST, чтобы указать столбец ключа партиционирования, а затем — определения партиций в круглых скобках через запятую.
Определение каждой партиции следует этому шаблону:
PARTITION <partition_name> VALUES (<list_value>[, ...])
где:
-
<partition_name>— пользовательский идентификатор, используемый вместо автоматически сгенерированного номера в полном имени партиции; -
<list_value>— одно или несколько значений ключа партиционирования, относящихся к данной партиции.
Многоуровневое партиционирование
Многоуровневое партиционирование сочетает партиционирование на основе диапазонов и списков значений на нескольких уровнях. Это позволяет делить партиции первого уровня на сабпартиции второго уровня, которые при необходимости можно разделить дальше.
Используйте выражение PARTITION BY (с RANGE или LIST), чтобы определить ключ партиционирования на первом уровне.
Для всех последующих уровней используйте выражение SUBPARTITION BY (также с RANGE или LIST).
Определения сабпартиций имеют тот же формат, как и обычные партиции, но с использованием ключевого слова SUBPARTITION вместо PARTITION.
Существует два способа определить сабпартиции — вручную или с помощью шаблона сабпартиций.
Определение сабпартиций вручную
В этом подходе каждая партиция и сабпартиция определяется явно.
Сначала укажите все ключи партиционирования с помощью выражений PARTITION BY и SUBPARTITION BY.
Затем перечислите спецификации партиций и сабпартиций.
Иерархия партиций и сабпартиций определяется с помощью вложенных круглых скобок, отражая их уровень в структуре партиционирования.
CREATE TABLE <table_name> (
<column_definitions>
)
[ PARTITION BY <partition_type> (<column>)
[ SUBPARTITION BY <partition_type> (<column1>) ]
[ SUBPARTITION BY <partition_type> (<column2>) ]
[...]
( <partition_spec>
[ ( <subpartition_spec_column1>
[ ( <subpartition_spec_column2>
[...] ) ] ) ],
[ <partition_spec>
[ ( <subpartition_spec_column1>
[ ( <subpartition_spec_column2>
[...] ) ] ) ], ]
[...]
) ]
Шаблоны сабпартиций
В этом подходе сабпартиции для каждого уровня иерархии задаются один раз с помощью выражения SUBPARTITION TEMPLATE, размещенного сразу после соответствующего выражения SUBPARTITION BY.
Использование шаблона сабпартиций обеспечивает единообразную структуру всех партиций, включая те, что будут добавлены в будущем.
CREATE TABLE <table_name> (
<column_definitions>
)
[ PARTITION BY <partition_type> (<column>)
{ [ SUBPARTITION BY <partition_type> (<column1>)
SUBPARTITION TEMPLATE ( <template_spec> ) ]
[ SUBPARTITION BY partition_type (<column2>)
SUBPARTITION TEMPLATE ( <template_spec> ) ]
[...] }
( <partition_spec> ) ]
Создание партиционированных таблиц
Временные диапазоны
Команда ниже создает таблицу с партиционированием по диапазону, где каждая партиция охватывает один месяц первого квартала 2025 года, а также включает партицию по умолчанию для выходящих за пределы диапазона дат:
CREATE TABLE sales
(
id INT,
date DATE,
amount DECIMAL(10, 2)
)
WITH (appendoptimized = true)
DISTRIBUTED BY (id)
PARTITION BY RANGE (date)
(
START (DATE '2025-01-01') INCLUSIVE
END (DATE '2025-04-01') EXCLUSIVE
EVERY (INTERVAL '1 month'),
DEFAULT PARTITION other_dates
);
Следующая команда создает такую же партиционированную таблицу sales, но определяет каждую партицию вручную:
CREATE TABLE sales
(
id INT,
date DATE,
amount DECIMAL(10, 2)
)
WITH (appendoptimized = true)
DISTRIBUTED BY (id)
PARTITION BY RANGE (date)
(
PARTITION jan_2025 START (DATE '2025-01-01') INCLUSIVE,
PARTITION feb_2025 START (DATE '2025-02-01') INCLUSIVE,
PARTITION mar_2025 START (DATE '2025-03-01') INCLUSIVE
END (DATE '2025-04-01') EXCLUSIVE,
DEFAULT PARTITION other_dates
);
Числовые диапазоны
Данная команда создает таблицу sales с партиционированием по диапазону значений на основе столбца amount:
CREATE TABLE sales
(
id INT,
date DATE,
amount DECIMAL(10, 2)
)
WITH (appendoptimized = true)
DISTRIBUTED BY (id)
PARTITION BY RANGE (amount)
(
START (0)
END (1000)
EVERY (250),
DEFAULT PARTITION out_of_range
);
Эта команда создает таблицу sales с вручную определенными партициями по диапазону значений:
CREATE TABLE sales
(
id INT,
date DATE,
amount DECIMAL(10, 2)
)
WITH (appendoptimized = true)
DISTRIBUTED BY (id)
PARTITION BY RANGE (amount)
(
PARTITION low_amounts START (0),
PARTITION medium_amounts START (100),
PARTITION high_amounts START (500)
END (1000),
DEFAULT PARTITION out_of_range);
Списки значений
Следующий SQL-запрос создает таблицу sales с партиционированием по region на основе списка значений.
Указаны явные партиции для Asia и Europe, а также партиция по умолчанию для остальных регионов:
CREATE TABLE sales
(
id INT,
date DATE,
region TEXT,
amount DECIMAL(10, 2)
)
WITH (appendoptimized = true)
DISTRIBUTED BY (id)
PARTITION BY LIST (region)
(
PARTITION asia VALUES ('Asia'),
PARTITION europe VALUES ('Europe'),
DEFAULT PARTITION other_regions
);
Многоуровневое партиционирование
Эта команда создает двухуровневую партиционированную таблицу sales: на первом уровне используется автоматическое партиционирование по диапазону по столбцу date, а на втором уровне с помощью SUBPARTITION TEMPLATE задаются дочерние сабпартиции по region:
CREATE TABLE sales
(
id INT,
date DATE,
region TEXT,
amount DECIMAL(10, 2)
)
WITH (appendoptimized = true)
DISTRIBUTED BY (id)
PARTITION BY RANGE (date)
SUBPARTITION BY LIST (region)
SUBPARTITION TEMPLATE
(
SUBPARTITION asia VALUES ('Asia'),
SUBPARTITION europe VALUES ('Europe'),
DEFAULT SUBPARTITION other_regions
)
(
START (DATE '2025-01-01') INCLUSIVE
END (DATE '2025-04-01') EXCLUSIVE
EVERY (INTERVAL '1 month'),
DEFAULT PARTITION other_dates
);
Следующая команда создает двухуровневую партиционированную таблицу sales с вручную заданными ежемесячными партициями по дате, каждая из которых содержит дочерние сабпартиции по region:
CREATE TABLE sales
(
id INT,
date DATE,
region TEXT,
amount DECIMAL(10, 2)
)
WITH (appendoptimized = true)
DISTRIBUTED BY (id)
PARTITION BY RANGE (date)
SUBPARTITION BY LIST (region)
(
PARTITION jan_2025 START (DATE '2025-01-01') INCLUSIVE (
SUBPARTITION asia VALUES ('Asia'),
SUBPARTITION europe VALUES ('Europe'),
DEFAULT SUBPARTITION other_regions
),
PARTITION feb_2025 START (DATE '2025-02-01') INCLUSIVE (
SUBPARTITION asia VALUES ('Asia'),
SUBPARTITION europe VALUES ('Europe'),
DEFAULT SUBPARTITION other_regions
),
PARTITION mar_2025 START (DATE '2025-03-01') INCLUSIVE (
SUBPARTITION asia VALUES ('Asia'),
SUBPARTITION europe VALUES ('Europe'),
DEFAULT SUBPARTITION other_regions
),
DEFAULT PARTITION other_dates (
SUBPARTITION asia VALUES ('Asia'),
SUBPARTITION europe VALUES ('Europe'),
DEFAULT SUBPARTITION other_regions
)
);
Следующая команда создает таблицу sales с трехуровневым партиционированием:
-
автоматическое партиционирование по диапазону по столбцу
date; -
сабпартиционирование по значениям
region; -
сабпартиционирование по диапазонам значений
amount.
Для обоих уровней сабпартиционирования используется SUBPARTITION TEMPLATE.
CREATE TABLE sales
(
id INT,
date DATE,
region TEXT,
amount DECIMAL(10, 2)
)
WITH (appendoptimized = true)
DISTRIBUTED BY (id)
PARTITION BY RANGE (date)
SUBPARTITION BY LIST (region)
SUBPARTITION TEMPLATE
(
SUBPARTITION asia VALUES ('Asia'),
SUBPARTITION europe VALUES ('Europe'),
DEFAULT SUBPARTITION other_regions
)
SUBPARTITION BY RANGE (amount)
SUBPARTITION TEMPLATE
(
START (0)
END (1000)
EVERY (100),
DEFAULT SUBPARTITION out_of_range
)
(
START (DATE '2025-01-01') INCLUSIVE
END (DATE '2025-04-01') EXCLUSIVE
EVERY (INTERVAL '1 month'),
DEFAULT PARTITION other_dates
);
Партиционирование существующей таблицы
Партиционирование таблицы можно указать только при ее создании. Если требуется партиционированная версия существующей таблицы, создайте новую партиционированную таблицу и загрузите в нее исходные данные:
-
Создайте новую партиционированную таблицу:
CREATE TABLE sales_partitioned ( LIKE sales ) WITH (appendoptimized = true) PARTITION BY RANGE (date) ( START (DATE '2025-01-01') INCLUSIVE END (DATE '2025-04-01') EXCLUSIVE EVERY (INTERVAL '1 month'), DEFAULT PARTITION other_dates ); -
Загрузите данные из исходной таблицы в новую:
INSERT INTO sales_partitioned SELECT * FROM sales; -
Удалите исходную таблицу:
DROP TABLE sales; -
Переименуйте новую таблицу, присвоив ей имя исходной таблицы:
ALTER TABLE sales_partitioned RENAME TO sales;
После создания новой таблицы необходимо заново выдать привилегии на таблицу. Узнайте больше в статье Роли и привилегии.
Просмотр информации о партиционировании
Ниже приведен пример партиционированной таблицы, используемой для демонстрации способов просмотра информации о партиционировании.
CREATE TABLE sales
(
id INT,
date DATE,
region TEXT,
amount DECIMAL(10, 2)
)
WITH (appendoptimized = true)
DISTRIBUTED BY (id)
PARTITION BY RANGE (date)
SUBPARTITION BY LIST (region)
SUBPARTITION TEMPLATE
(
SUBPARTITION asia VALUES ('Asia'),
SUBPARTITION europe VALUES ('Europe'),
DEFAULT SUBPARTITION other_regions
)
(
START (DATE '2025-01-01') INCLUSIVE
END (DATE '2025-04-01') EXCLUSIVE
EVERY (INTERVAL '1 month'),
DEFAULT PARTITION other_dates
);
Метакоманды psql
Метакоманда \d+ выводит информацию о таблице sales:
\d+ sales
Раздел Partitions в выводе содержит список дочерних таблиц, связанных с родительской таблицей:
Partitioned table "public.sales"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
--------+---------------+-----------+----------+---------+----------+--------------+-------------
id | integer | | | | plain | |
date | date | | | | plain | |
region | text | | | | extended | |
amount | numeric(10,2) | | | | main | |
Partition key: RANGE (date)
Partitions: sales_1_prt_2 FOR VALUES FROM ('2025-01-01') TO ('2025-02-01'), PARTITIONED,
sales_1_prt_3 FOR VALUES FROM ('2025-02-01') TO ('2025-03-01'), PARTITIONED,
sales_1_prt_4 FOR VALUES FROM ('2025-03-01') TO ('2025-04-01'), PARTITIONED,
sales_1_prt_other_dates DEFAULT, PARTITIONED
Distributed by: (id)
Access method: ao_row
Вы можете выполнить ту же команду для дочерней таблицы, чтобы увидеть ее дочерние таблицы, используемые для сабпартиционирования:
\d+ sales_1_prt_2
В дополнение к разделу Partitions в вывод также включается раздел Partition of, указывающий, что эта таблица наследует столбцы и ограничения таблицы sales:
Partitioned table "public.sales_1_prt_2"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
--------+---------------+-----------+----------+---------+----------+--------------+-------------
id | integer | | | | plain | |
date | date | | | | plain | |
region | text | | | | extended | |
amount | numeric(10,2) | | | | main | |
Partition of: sales FOR VALUES FROM ('2025-01-01') TO ('2025-02-01')
Partition constraint: ((date IS NOT NULL) AND (date >= '2025-01-01'::date) AND (date < '2025-02-01'::date))
Partition key: LIST (region)
Partitions: sales_1_prt_2_2_prt_asia FOR VALUES IN ('Asia'),
sales_1_prt_2_2_prt_europe FOR VALUES IN ('Europe'),
sales_1_prt_2_2_prt_other_regions DEFAULT
Distributed by: (id)
Access method: ao_row
Системные каталоги
Чтобы получить информацию о партиционированных таблицах в текущей базе данных, используйте один из описанных ниже способов.
pg_catalog.pg_partitioned_table
Чтобы вывести все партиционированные таблицы, выполните следующий запрос к таблице pg_partitioned_table:
SELECT pg_class.relname AS partition_table_name,
pg_attribute.attname AS column_in_partition_key,
class2.relname AS default_partition,
pg_partitioned_table.partstrat AS partition_type
FROM pg_partitioned_table
INNER JOIN pg_class ON pg_class.oid = pg_partitioned_table.partrelid
INNER JOIN pg_attribute ON pg_attribute.attnum IN (SELECT unnest(pg_partitioned_table.partattrs)) AND
pg_attribute.attrelid = pg_class.oid
LEFT JOIN pg_class class2 ON class2.oid = pg_partitioned_table.partdefid
ORDER BY pg_class.relname;
Результат:
partition_table_name | column_in_partition_key | default_partition | partition_type -------------------------+-------------------------+---------------------------------------------+---------------- sales | date | sales_1_prt_other_dates | r sales_1_prt_2 | region | sales_1_prt_2_2_prt_other_regions | l sales_1_prt_3 | region | sales_1_prt_3_2_prt_other_regions | l sales_1_prt_4 | region | sales_1_prt_4_2_prt_other_regions | l sales_1_prt_other_dates | region | sales_1_prt_other_dates_2_prt_other_regions | l (5 rows)
Эта команда возвращает следующие данные:
-
partition_table_name— полное имя таблицы, используемое для обращения к партиции напрямую в DML-командах. -
column_in_partition_key— имя столбца, используемого в качестве ключа партиционирования. -
default_partition— название партиции, используемой по умолчанию (при ее наличии). -
partition_type— тип партиционирования (r— на основе диапазонов,l— на основе списков значений).
Обратите внимание, что листовые партиции в результатах запроса не выводятся.
gp_toolkit.gp_partitions
Начиная с Greengage DB 7 системное представление gp_toolkit.gp_partitions заменяет pg_catalog.pg_partitions.
Чтобы показать схему партиционирования указанной таблицы, выполните SQL-запрос к системному представлению gp_toolkit.gp_partitions:
SELECT partitiontablename,
partitiontype,
partitionlevel,
partitionrank
FROM gp_toolkit.gp_partitions
WHERE tablename = 'sales'
ORDER BY partitionlevel,
partitionrank;
Результат может выглядеть следующим образом:
partitiontablename | partitiontype | partitionlevel | partitionrank ---------------------------------------------+---------------+----------------+--------------- sales_1_prt_2 | range | 1 | 1 sales_1_prt_3 | range | 1 | 2 sales_1_prt_4 | range | 1 | 3 sales_1_prt_other_dates | range | 1 | sales_1_prt_2_2_prt_asia | list | 2 | sales_1_prt_2_2_prt_europe | list | 2 | sales_1_prt_2_2_prt_other_regions | list | 2 | sales_1_prt_3_2_prt_asia | list | 2 | sales_1_prt_3_2_prt_europe | list | 2 | sales_1_prt_3_2_prt_other_regions | list | 2 | sales_1_prt_4_2_prt_asia | list | 2 | sales_1_prt_4_2_prt_europe | list | 2 | sales_1_prt_4_2_prt_other_regions | list | 2 | sales_1_prt_other_dates_2_prt_asia | list | 2 | sales_1_prt_other_dates_2_prt_europe | list | 2 | sales_1_prt_other_dates_2_prt_other_regions | list | 2 | (16 rows)
Таблица содержит следующие столбцы:
-
partitiontablename— полное имя таблицы, используемое для обращения к партиции напрямую в DML-командах. -
partitiontype— тип партиционирования. -
partitionlevel— уровень партиции в иерархии. -
partitionrank— порядковый номер (rank) партиции в общем списке партиций на текущем уровне (начиная с1). Заполняется только для range-партиций.
Вы также можете использовать столбец partitionboundary для получения полных спецификаций партиций.
pg_catalog.gp_partition_template
Представление pg_partition_templates удалено в Greengage DB 7.
Для партиционированных таблиц, созданных с использованием классического синтаксиса, системная таблица gp_partition_template описывает связь между партиционированной таблицей и шаблоном сабпартиций, определенным на каждом уровне иерархии.
Чтобы просмотреть шаблон в более удобочитаемом виде, используйте функцию pg_get_expr() с gp_partition_template, например:
SELECT level, pg_get_expr(template, relid)
FROM gp_partition_template
WHERE relid::regclass::text = 'sales';
Результат:
level | pg_get_expr
-------+-------------------------------------------------------------------------------------------------------------------------------------
1 | SUBPARTITION TEMPLATE(DEFAULT SUBPARTITION other_regions, SUBPARTITION asia VALUES ('Asia'), SUBPARTITION europe VALUES ('Europe'))
(1 row)
Системные функции
Для получения информации о партиционированных таблицах можно использовать следующие функции:
- pg_partition_tree(regclass)
-
Возвращает по одной строке для каждой таблицы или индекса в иерархии партиций указанной партиционированной таблицы или партиционированного индекса. Результат включает имя партиции, ее непосредственного родителя, флаг, указывающий, является ли она листовой партицией, и ее уровень в иерархии. Уровень начинается с
0для корневой таблицы,1— для ее непосредственных партиций,2— для партиций следующего уровня и далее по иерархии.Возвращаемый тип:
setof record - pg_partition_ancestors(regclass)
-
Возвращает все родительские отношения указанной партиции, включая саму партицию.
Возвращаемый тип:
setof regclass - pg_partition_root(regclass)
-
Возвращает родителя верхнего уровня иерархии партиционирования, к которой принадлежит указанное отношение.
Возвращаемый тип:
regclass
Следующая команда отображает иерархию партиций для промежуточной таблицы sales_1_prt_2:
SELECT * FROM pg_partition_tree('sales_1_prt_2');
Результат:
relid | parentrelid | isleaf | level -----------------------------------+---------------+--------+------- sales_1_prt_2 | sales | f | 0 sales_1_prt_2_2_prt_other_regions | sales_1_prt_2 | t | 1 sales_1_prt_2_2_prt_asia | sales_1_prt_2 | t | 1 sales_1_prt_2_2_prt_europe | sales_1_prt_2 | t | 1 (4 rows)
Обслуживание партиционированных таблиц
Добавление партиции по умолчанию
CREATE TABLE sales
(
id INT,
date DATE,
region TEXT,
amount DECIMAL(10, 2)
)
WITH (appendoptimized = true)
DISTRIBUTED BY (id)
PARTITION BY RANGE (date)
SUBPARTITION BY LIST (region)
SUBPARTITION TEMPLATE
(
SUBPARTITION asia VALUES ('Asia'),
SUBPARTITION europe VALUES ('Europe')
)
(
START (DATE '2025-01-01') INCLUSIVE
END (DATE '2025-04-01') EXCLUSIVE
EVERY (INTERVAL '1 month')
);
Вы можете добавить партицию по умолчанию в схему партиционирования с помощью команды ALTER TABLE:
ALTER TABLE sales
ADD DEFAULT PARTITION other_dates;
Если ваша схема партиционирования многоуровневая, партиция по умолчанию должна быть на каждом уровне иерархии:
ALTER TABLE sales
ALTER PARTITION FOR ('2025-01-01')
ADD DEFAULT PARTITION other_regions;
ALTER TABLE sales
ALTER PARTITION FOR ('2025-02-01')
ADD DEFAULT PARTITION other_regions;
ALTER TABLE sales
ALTER PARTITION FOR ('2025-03-01')
ADD DEFAULT PARTITION other_regions;
Начиная с Greengage DB 7 выражение FOR (RANK(<value>)) не поддерживается.
Чтобы убедиться, что партиции по умолчанию добавлены, выполните следующий SQL-запрос:
SELECT partitiontablename,
partitiontype,
partitionlevel,
partitionrank
FROM gp_toolkit.gp_partitions
WHERE tablename = 'sales'
ORDER BY partitionlevel,
partitionrank;
Вывод должен включать таблицы sales_1_prt_other_dates и sales_1_prt_*_other_regions:
partitiontablename | partitiontype | partitionlevel | partitionrank --------------------------------------+---------------+----------------+--------------- sales_1_prt_1 | range | 1 | 1 sales_1_prt_2 | range | 1 | 2 sales_1_prt_3 | range | 1 | 3 sales_1_prt_other_dates | range | 1 | sales_1_prt_1_2_prt_asia | list | 2 | sales_1_prt_1_2_prt_europe | list | 2 | sales_1_prt_1_2_prt_other_regions | list | 2 | sales_1_prt_2_2_prt_asia | list | 2 | sales_1_prt_2_2_prt_europe | list | 2 | sales_1_prt_2_2_prt_other_regions | list | 2 | sales_1_prt_3_2_prt_asia | list | 2 | sales_1_prt_3_2_prt_europe | list | 2 | sales_1_prt_3_2_prt_other_regions | list | 2 | sales_1_prt_other_dates_2_prt_asia | list | 2 | sales_1_prt_other_dates_2_prt_europe | list | 2 | (15 rows)
Добавление новой партиции
CREATE TABLE sales
(
id INT,
date DATE,
region TEXT,
amount DECIMAL(10, 2)
)
WITH (appendoptimized = true)
DISTRIBUTED BY (id)
PARTITION BY RANGE (date)
SUBPARTITION BY LIST (region)
SUBPARTITION TEMPLATE
(
SUBPARTITION asia VALUES ('Asia'),
SUBPARTITION europe VALUES ('Europe')
)
(
PARTITION jan_2025 START (DATE '2025-01-01') INCLUSIVE ,
PARTITION feb_2025 START (DATE '2025-02-01') INCLUSIVE ,
PARTITION mar_2025 START (DATE '2025-03-01') INCLUSIVE
END (DATE '2025-04-01') EXCLUSIVE
);
Вы можете добавить новую партицию с помощью команды ALTER TABLE.
Если исходная схема партиционирования использует шаблон сабпартиционирования, то вновь добавленная партиция будет автоматически партиционирована в соответствии с этим шаблоном.
Следующая команда добавляет новую партицию для апреля 2025 года в таблицу sales:
ALTER TABLE sales
ADD PARTITION apr_2025 START (DATE '2025-04-01')
END (DATE '2025-05-01') EXCLUSIVE;
Когда вы добавляете сабпартицию в существующую партицию, вы можете указать партицию для изменения:
ALTER TABLE sales
ALTER PARTITION FOR ('2025-04-01')
ADD PARTITION africa VALUES ('Africa');
Чтобы проверить, что новые партиции добавлены, выполните следующий запрос:
SELECT partitiontablename,
partitiontype,
partitionlevel,
partitionrank
FROM gp_toolkit.gp_partitions
WHERE tablename = 'sales'
ORDER BY partitionlevel,
partitionrank;
Результат включает партиции sales_1_prt_apr_2025 и sales_1_prt_apr_2025_2_prt_africa:
partitiontablename | partitiontype | partitionlevel | partitionrank -----------------------------------+---------------+----------------+--------------- sales_1_prt_jan_2025 | range | 1 | 1 sales_1_prt_feb_2025 | range | 1 | 2 sales_1_prt_mar_2025 | range | 1 | 3 sales_1_prt_apr_2025 | range | 1 | 4 sales_1_prt_jan_2025_2_prt_asia | list | 2 | sales_1_prt_jan_2025_2_prt_europe | list | 2 | sales_1_prt_feb_2025_2_prt_asia | list | 2 | sales_1_prt_feb_2025_2_prt_europe | list | 2 | sales_1_prt_mar_2025_2_prt_asia | list | 2 | sales_1_prt_mar_2025_2_prt_europe | list | 2 | sales_1_prt_apr_2025_2_prt_africa | list | 2 | sales_1_prt_apr_2025_2_prt_asia | list | 2 | sales_1_prt_apr_2025_2_prt_europe | list | 2 | (13 rows)
Вы не можете добавить партицию в схему партиционирования, если в ней есть партиция по умолчанию. Для добавления партиции необходимо разделить партицию по умолчанию. Узнайте подробнее в разделе Разделение партиции по умолчанию.
Разделение партиции
Разделение указанной партиции
CREATE TABLE sales
(
id INT,
date DATE,
amount DECIMAL(10, 2)
)
WITH (appendoptimized = true)
DISTRIBUTED BY (id)
PARTITION BY RANGE (date)
(
PARTITION jan_2025 START (DATE '2025-01-01') INCLUSIVE ,
PARTITION feb_2025 START (DATE '2025-02-01') INCLUSIVE ,
PARTITION mar_2025 START (DATE '2025-03-01') INCLUSIVE
END (DATE '2025-04-01') EXCLUSIVE
);
Разделение партиции разбивает существующую партицию на две новые.
Вы можете разделить партицию с помощью команды ALTER TABLE.
Указанное при разделении значение попадает во вторую (новую) партицию.
Обратите внимание, что разделять можно только партиции самого нижнего уровня — те, которые фактически содержат данные. Для одноуровневого партиционирования можно разделять как range-, так и list-партиции, а для многоуровневого — только range-партиции.
Выполните следующую команду, чтобы разделить месячную партицию на две: первую — для дат с 1 по 15 марта, вторую — для дат с 16 по 31 марта:
ALTER TABLE sales
SPLIT PARTITION FOR ('2025-03-01')
AT ('2025-03-16')
INTO (PARTITION mar_1to15_2025, PARTITION mar_16to31_2025);
Чтобы увидеть обновленную схему партиционирования таблицы, выполните следующий SQL-запрос:
SELECT partitiontablename,
partitionrangestart,
partitionrangeend
FROM gp_toolkit.gp_partitions
WHERE tablename = 'sales';
Результат выглядит следующим образом:
partitiontablename | partitionrangestart | partitionrangeend -----------------------------+---------------------+------------------- sales_1_prt_jan_2025 | '2025-01-01' | '2025-02-01' sales_1_prt_feb_2025 | '2025-02-01' | '2025-03-01' sales_1_prt_mar_1to15_2025 | '2025-03-01' | '2025-03-16' sales_1_prt_mar_16to31_2025 | '2025-03-16' | '2025-04-01' (4 rows)
Разделение партиции по умолчанию
CREATE TABLE sales
(
id INT,
date DATE,
amount DECIMAL(10, 2)
)
WITH (appendoptimized = true)
DISTRIBUTED BY (id)
PARTITION BY RANGE (date)
(
PARTITION jan_2025 START (DATE '2025-01-01') INCLUSIVE ,
PARTITION feb_2025 START (DATE '2025-02-01') INCLUSIVE ,
PARTITION mar_2025 START (DATE '2025-03-01') INCLUSIVE
END (DATE '2025-04-01') EXCLUSIVE,
DEFAULT PARTITION other_dates
);
Чтобы разделить партицию по умолчанию, используйте выражение SPLIT DEFAULT PARTITION:
ALTER TABLE sales
SPLIT DEFAULT PARTITION
START ('2025-04-01') INCLUSIVE
END ('2025-05-01') EXCLUSIVE
INTO (PARTITION apr_2025, DEFAULT PARTITION);
Чтобы увидеть обновленную схему партиционирования, выполните следующий SQL-запрос:
SELECT partitiontablename,
partitionrangestart,
partitionrangeend
FROM gp_toolkit.gp_partitions
WHERE tablename = 'sales';
Результат должен выглядеть так:
partitiontablename | partitionrangestart | partitionrangeend -------------------------+---------------------+------------------- sales_1_prt_jan_2025 | '2025-01-01' | '2025-02-01' sales_1_prt_feb_2025 | '2025-02-01' | '2025-03-01' sales_1_prt_mar_2025 | '2025-03-01' | '2025-04-01' sales_1_prt_apr_2025 | '2025-04-01' | '2025-05-01' sales_1_prt_other_dates | | (5 rows)
Изменение шаблона сабпартиционирования
CREATE TABLE sales
(
id INT,
date DATE,
region TEXT,
amount DECIMAL(10, 2)
)
WITH (appendoptimized = true)
DISTRIBUTED BY (id)
PARTITION BY RANGE (date)
SUBPARTITION BY LIST (region)
SUBPARTITION TEMPLATE
(
SUBPARTITION asia VALUES ('Asia'),
SUBPARTITION europe VALUES ('Europe')
)
(
PARTITION jan_2025 START (DATE '2025-01-01') INCLUSIVE ,
PARTITION feb_2025 START (DATE '2025-02-01') INCLUSIVE ,
PARTITION mar_2025 START (DATE '2025-03-01') INCLUSIVE
END (DATE '2025-04-01') EXCLUSIVE
);
Используйте выражение SET SUBPARTITION TEMPLATE, чтобы изменить шаблон сабпартиций для партиционированной таблицы.
Партиции, добавленные после указания нового шаблона сабпартиций, будут иметь новую схему партиционирования.
Существующие партиции не изменяются.
В следующем примере изменяется шаблон сабпартиции таблицы sales:
ALTER TABLE sales
SET SUBPARTITION TEMPLATE
(SUBPARTITION asia VALUES ('Asia'),
SUBPARTITION europe VALUES ('Europe'),
SUBPARTITION africa VALUES ('Africa'),
DEFAULT SUBPARTITION other_regions);
Когда вы добавляете новую партицию диапазона дат, она должна включать новую сабпартицию для значения Africa:
ALTER TABLE sales
ADD PARTITION apr_2025 START (DATE '2025-04-01')
END (DATE '2025-05-01') EXCLUSIVE;
Чтобы просмотреть обновленную схему партиционирования, выполните следующий SQL-запрос:
SELECT partitiontablename,
partitiontype,
partitionlevel,
partitionrank
FROM gp_toolkit.gp_partitions
WHERE tablename = 'sales'
ORDER BY partitionlevel,
partitionrank;
Результат должен включать сабпартиции asia, europe, africa и партицию по умолчанию с именем other_regions:
partitiontablename | partitiontype | partitionlevel | partitionrank ------------------------------------------+---------------+----------------+--------------- sales_1_prt_jan_2025 | range | 1 | 1 sales_1_prt_feb_2025 | range | 1 | 2 sales_1_prt_mar_2025 | range | 1 | 3 sales_1_prt_apr_2025 | range | 1 | 4 sales_1_prt_jan_2025_2_prt_asia | list | 2 | sales_1_prt_jan_2025_2_prt_europe | list | 2 | sales_1_prt_feb_2025_2_prt_asia | list | 2 | sales_1_prt_feb_2025_2_prt_europe | list | 2 | sales_1_prt_mar_2025_2_prt_asia | list | 2 | sales_1_prt_mar_2025_2_prt_europe | list | 2 | sales_1_prt_apr_2025_2_prt_africa | list | 2 | sales_1_prt_apr_2025_2_prt_asia | list | 2 | sales_1_prt_apr_2025_2_prt_europe | list | 2 | sales_1_prt_apr_2025_2_prt_other_regions | list | 2 | (14 rows)
Обмен партиции
CREATE TABLE sales
(
id INT,
date DATE,
amount DECIMAL(10, 2)
)
WITH (appendoptimized = true)
DISTRIBUTED BY (id)
PARTITION BY RANGE (date)
(
PARTITION jan_2025 START (DATE '2025-01-01') INCLUSIVE ,
PARTITION feb_2025 START (DATE '2025-02-01') INCLUSIVE ,
PARTITION mar_2025 START (DATE '2025-03-01') INCLUSIVE
END (DATE '2025-04-01') EXCLUSIVE,
DEFAULT PARTITION other_dates
);
Обмен партициями позволяет заменить партицию таблицы на другую таблицу с такой же структурой, которая обычно называется staging-таблицей. После обмена партиция содержит данные из staging-таблицы, а staging-таблица — исходные данные партиции.
Эта возможность полезна для загрузки данных, так как вставка данных напрямую в партиционированные таблицы может быть неэффективной. Кроме того, обмен партициями можно использовать для изменения типа хранения существующих партиций.
Чтобы продемонстрировать обмен партициями, сначала добавьте тестовые данные в таблицу sales:
INSERT INTO sales (id, date, amount)
SELECT gs.id,
DATE '2025-01-01' + (gs.id % 59),
round((random() * 1000)::NUMERIC, 2)
FROM generate_series(1, 40000) AS gs(id);
Проверьте, что таблица, соответствующая партиции mar_2025, не содержит данных:
SELECT count(*)
FROM sales_1_prt_mar_2025;
Создайте таблицу с такой же структурой, как у партиционированной таблицы, но с другим типом хранения:
CREATE TABLE stg_mar_2025
(
LIKE sales
)
WITH (appendoptimized = false);
Добавьте данные в таблицу:
INSERT INTO stg_mar_2025 (id, date, amount)
SELECT gs.id,
DATE '2025-03-01' + (gs.id % 31),
round((random() * 1000)::NUMERIC, 2)
FROM generate_series(1, 20000) AS gs(id);
Для обмена партиции используйте команду ALTER TABLE с выражением EXCHANGE PARTITION:
ALTER TABLE sales
EXCHANGE PARTITION FOR (DATE '2025-03-01')
WITH TABLE stg_mar_2025 WITH VALIDATION;
Проверьте, что таблица, соответствующая партиции mar_2025, теперь содержит данные:
SELECT count(*)
FROM sales_1_prt_mar_2025;
Результат должен выглядеть следующим образом:
count ------- 20000 (1 row)
Убедитесь, что тип хранения данных в партиции также изменился:
\dt+ sales*
Результат должен показать, что тип хранения для sales_1_prt_mar_2025 — heap:
List of relations Schema | Name | Type | Owner | Storage | Size | Description --------+-------------------------+-------------------+---------+---------+---------+------------- public | sales | partitioned table | gpadmin | ao_row | 0 bytes | public | sales_1_prt_feb_2025 | table | gpadmin | ao_row | 771 kB | public | sales_1_prt_jan_2025 | table | gpadmin | ao_row | 822 kB | public | sales_1_prt_mar_2025 | table | gpadmin | heap | 1280 kB | public | sales_1_prt_other_dates | table | gpadmin | ao_row | 160 kB | (5 rows)
Перед обменом партиции по умолчанию убедитесь, что данные в staging-таблице корректны и не принадлежат каким-либо дочерним партициям.
В противном случае запросы, использующие GPORCA, могут возвращать неверные результаты или приводить к повреждению данных после операций UPDATE и DELETE.
Переименование партиции
CREATE TABLE sales
(
id INT,
date DATE,
region TEXT,
amount DECIMAL(10, 2)
)
WITH (appendoptimized = true)
DISTRIBUTED BY (id)
PARTITION BY RANGE (date)
SUBPARTITION BY LIST (region)
SUBPARTITION TEMPLATE
(
SUBPARTITION asia VALUES ('Asia'),
SUBPARTITION europe VALUES ('Europe')
)
(
START (DATE '2025-01-01') INCLUSIVE
END (DATE '2025-04-01') EXCLUSIVE
EVERY (INTERVAL '1 month')
);
Данная команда переименовывает верхнеуровневую родительскую таблицу:
ALTER TABLE sales
RENAME TO globalsales;
Обратите внимание, что это автоматически изменяет префиксы имен всех ее дочерних таблиц.
Чтобы изменить имя партиции, используйте команду ALTER TABLE с выражением RENAME PARTITION:
ALTER TABLE globalsales
RENAME PARTITION FOR ('2025-01-01') TO jan_2025;
ALTER TABLE globalsales
RENAME PARTITION FOR ('2025-02-01') TO feb_2025;
ALTER TABLE globalsales
RENAME PARTITION FOR ('2025-03-01') TO mar_2025;
Для проверки новых имен партиций используйте следующий запрос:
SELECT DISTINCT partitiontablename,
partitiontype,
partitionlevel,
partitionrank
FROM gp_toolkit.gp_partitions
WHERE tablename = 'globalsales'
ORDER BY partitionlevel, partitionrank NULLS LAST, partitiontablename;
Результат должен выглядеть так:
partitiontablename | partitiontype | partitionlevel | partitionrank -----------------------------------------+---------------+----------------+--------------- globalsales_1_prt_jan_2025 | range | 1 | 1 globalsales_1_prt_feb_2025 | range | 1 | 2 globalsales_1_prt_mar_2025 | range | 1 | 3 globalsales_1_prt_feb_2025_2_prt_asia | list | 2 | globalsales_1_prt_feb_2025_2_prt_europe | list | 2 | globalsales_1_prt_jan_2025_2_prt_asia | list | 2 | globalsales_1_prt_jan_2025_2_prt_europe | list | 2 | globalsales_1_prt_mar_2025_2_prt_asia | list | 2 | globalsales_1_prt_mar_2025_2_prt_europe | list | 2 | (9 rows)
Удаление данных из партиции
CREATE TABLE sales
(
id INT,
date DATE,
region TEXT,
amount DECIMAL(10, 2)
)
WITH (appendoptimized = true)
DISTRIBUTED BY (id)
PARTITION BY RANGE (date)
SUBPARTITION BY LIST (region)
SUBPARTITION TEMPLATE
(
SUBPARTITION asia VALUES ('Asia'),
SUBPARTITION europe VALUES ('Europe')
)
(
PARTITION jan_2025 START (DATE '2025-01-01') INCLUSIVE ,
PARTITION feb_2025 START (DATE '2025-02-01') INCLUSIVE ,
PARTITION mar_2025 START (DATE '2025-03-01') INCLUSIVE
END (DATE '2025-04-01') EXCLUSIVE
);
Чтобы удалить все данные из указанной партиции без удаления самой партиции, используйте команду ALTER TABLE с выражением TRUNCATE PARTITION.
Вставьте данные в таблицу:
INSERT INTO sales (id, date, region, amount)
SELECT gs.id,
DATE '2025-01-01' + (gs.id % 90),
CASE WHEN gs.id % 2 = 0 THEN 'Asia' ELSE 'Europe' END,
round((random() * 1000)::NUMERIC, 2)
FROM generate_series(1, 40000) AS gs(id);
Просмотрите информацию о доступных партициях:
SELECT partitiontablename,
partitiontype,
partitionlevel,
partitionrank
FROM gp_toolkit.gp_partitions
WHERE tablename = 'sales'
ORDER BY partitionlevel,
partitionrank;
Результат должен выглядеть так:
partitiontablename | partitiontype | partitionlevel | partitionrank -----------------------------------+---------------+----------------+--------------- sales_1_prt_jan_2025 | range | 1 | 1 sales_1_prt_feb_2025 | range | 1 | 2 sales_1_prt_mar_2025 | range | 1 | 3 sales_1_prt_jan_2025_2_prt_asia | list | 2 | sales_1_prt_jan_2025_2_prt_europe | list | 2 | sales_1_prt_feb_2025_2_prt_asia | list | 2 | sales_1_prt_feb_2025_2_prt_europe | list | 2 | sales_1_prt_mar_2025_2_prt_asia | list | 2 | sales_1_prt_mar_2025_2_prt_europe | list | 2 | (9 rows)
Проверьте количество строк в таблице sales_1_prt_jan_2025, соответствующей промежуточной партиции:
SELECT count(*)
FROM sales_1_prt_jan_2025;
Результат может выглядеть так:
count ------- 13794
Затем проверьте, что таблица sales_1_prt_feb_2025_2_prt_asia, соответствующая дочерней партиции, также содержит данные:
SELECT count(*)
FROM sales_1_prt_feb_2025_2_prt_asia;
Для удаления данных из промежуточной партиции jan_2025 используйте следующую команду:
ALTER TABLE sales
TRUNCATE PARTITION jan_2025;
Чтобы удалить данные из сабпартиции asia партиции feb_2025, используйте следующий SQL-запрос:
ALTER TABLE sales
ALTER PARTITION feb_2025
TRUNCATE PARTITION asia;
Затем снова используйте команду SELECT count(*), чтобы проверить, что количество строк равно 0 для обеих партиций.
Удаление партиции
Чтобы удалить указанную партицию, используйте команду ALTER TABLE с выражением DROP PARTITION.
В следующем примере удаляется партиция jan_2025 из таблицы sales, созданной в разделе Удаление данных из партиции:
ALTER TABLE sales
DROP PARTITION jan_2025;
Убедитесь, что партиция больше не существует, выполнив запрос к gp_toolkit.gp_partitions:
SELECT partitiontablename,
partitiontype,
partitionlevel,
partitionrank
FROM gp_toolkit.gp_partitions
WHERE tablename = 'sales'
ORDER BY partitionlevel,
partitionrank;
Результат должен выглядеть следующим образом:
partitiontablename | partitiontype | partitionlevel | partitionrank -----------------------------------+---------------+----------------+--------------- sales_1_prt_feb_2025 | range | 1 | 1 sales_1_prt_mar_2025 | range | 1 | 2 sales_1_prt_feb_2025_2_prt_asia | list | 2 | sales_1_prt_feb_2025_2_prt_europe | list | 2 | sales_1_prt_mar_2025_2_prt_asia | list | 2 | sales_1_prt_mar_2025_2_prt_europe | list | 2 | (6 rows)
Ограничения
Общие ограничения
К партиционированным таблицам Greengage DB применяются следующие ограничения:
-
Партиционированная таблица может иметь не более 32767 партиций на каждом уровне иерархии.
-
Таблицы, созданные с использованием политики распределения данных
DISTRIBUTED REPLICATED, не могут быть партиционированы. -
Если для партиционированной таблицы определено ограничение
PRIMARY KEYилиUNIQUE, оно должно включать все столбцы ключа партиционирования. Уникальный индекс может не включать столбцы ключа партиционирования; в этом случае уникальность обеспечивается только в пределах отдельных партиций, а не всей таблицы. -
Оптимизатор запросов GPORCA поддерживает однородные многоуровневые партиционированные таблицы. Если GPORCA включен (по умолчанию) и многоуровневая партиционированная таблица не является однородной, запросы выполняются с использованием планировщика PostgreSQL.
Ограничения внешних таблиц-партиций
-
Внешняя таблица, выступающая в роли партиции, является таблицей только для чтения. Операции, которые пытаются изменить данные в такой партиции, завершаются ошибкой:
-
Операции
INSERT,UPDATEиDELETEнад внешней таблицей-партицией завершаются ошибкой. -
Операции
TRUNCATEнад внешней таблицей-партицией завершаются ошибкой. -
Операция
COPYне может выполнять запись в партиционированную таблицу, если она включает внешнюю таблицу-партицию. -
Операции
COPY, которые читают из партиционированной таблицы, завершаются ошибкой, если таблица содержит внешнюю таблицу-партицию и не указано выражениеIGNORE EXTERNAL PARTITIONS. Если выражение указано, внешние таблицы-партиции пропускаются.Чтобы использовать
COPYс партиционированной таблицей, у которой есть дочерняя листовая партиция, являющаяся внешней таблицей, используйте SQL-запрос. Например, если таблицаsalesсодержит дочернюю листовую партицию, являющуюся внешней таблицей, следующая команда отправляет данные в стандартный вывод (stdout):COPY (SELECT * FROM sales) TO STDOUT;
-
-
Следующие операции поддерживаются только при условии, что данные во внешней таблице-партиции не изменяются:
-
Добавление или удаление столбца.
-
Изменение типа данных столбца.
-
-
Операции
ALTER TABLE … ALTER PARTITIONне поддерживаются, если партиционированная таблица содержит внешнюю таблицу-партицию:-
Задание шаблона сабпартиции.
-
Изменение свойств партиции.
-
Создание партиции по умолчанию.
-
Задание политики распределения.
-
Добавление или удаление ограничения
NOT NULLдля столбца. -
Добавление или удаление ограничений.
-
Разделение внешней партиции.
-
-
Утилита gpbackup не создает резервную копию данных листовой партиции, если эта партиция является читающей внешней таблицей.