F.33. pg_archive#
F.33. pg_archive #
pg_archive - это расширение для автоматического архивирования исторических данных из секционированных таблиц путем преобразования секций в методы хранения, которые более подходят для огромных объемов холодных, только для чтения или в основном для чтения данных по сравнению с обычными таблицами PostgreSQL. В настоящее время единственным поддерживаемым архивным хранилищем является колонный метод доступа, поддерживаемый проектом Hydra, но в будущем могут быть добавлены и другие методы.
Код в общих чертах основан на отличном проекте pg_partman.
Автоматическое обслуживание для архивирования разделов на основе предоставленных пользователем
политик реализовано с помощью фонового рабочего процесса, который периодически
выполняет хранимую процедуру pg_archive_run_maintenance_proc()
.
Процедура проверяет разделенные таблицы, управляемые pg_archive, и преобразует разделы, содержащие данные старше
временного интервала, указанного в политике для каждой таблицы.
pg_archive_run_maintenance_proc()
также может быть
вызвана вручную пользователем, когда требуется незапланированное обслуживание.
F.33.1. Установка #
Требования:
F.33.1.2. Настройка #
Фоновый рабочий процесс должен быть загружен при запуске базы данных путем добавления
библиотеки в shared_preload_libraries
в
postgresql.conf
shared_preload_libraries = 'pg_archive_bgw' # (change requires a restart)
Другие GUC, которые должны быть настроены перед использованием расширения,
это interval
, который представляет собой временной интервал в
секундах между запусками обслуживания фоновым процессом,
dbname
, который является CSV строкой базы(баз) данных для
обслуживания, и role
, которая является ролью, используемой
рабочим процессом: Вот пример:
pg_archive_bgw.interval = 3600 pg_archive_bgw.role = 'alex' pg_archive_bgw.dbname = 'mydb'
Роль должна иметь разрешения на выполнение
pg_archive_run_maintenance_proc()
.
Установка расширения после запуска сервера с необходимыми настроенными параметрами GUC:
CREATE SCHEMA archive; CREATE EXTENSION pg_archive SCHEMA archive;
F.33.2. Обновление #
ALTER EXTENSION pg_archive UPDATE TO '<latest version>';
F.33.3. Использование #
Разделенные таблицы могут быть настроены для управления с помощью pg_archive
с функцией pg_archive_manage()
.
Этот и последующие примеры в этом разделе предполагают, что pg_archive
установлен в схеме archive
, а
таблицы находятся в схеме monitoring
:
SELECT archive.pg_archive_manage('monitoring.metrics', 'metric_timestamp', '1 year'); pg_archive_manage ------------------- t (1 row)
Вышеуказанный вызов добавляет запись в таблицу
archive.pg_archive_config
, которая позже будет
использована pg_archive_run_maintenance_proc()
для
архивирования и, при необходимости, отсоединения разделов с данными старше 1
года в таблице metrics
в
схеме monitoring
на основе
значения metrics_timestamp
.
Когда таблица становится управляемой pg_archive, её разделы будут
проверены и, возможно, архивированы при следующем запланированном вызове
pg_archive_run_maintenance_proc()
фоновым
рабочим процессом, который по умолчанию настроен на запуск каждые 3600 секунд. В качестве альтернативы, вы можете вызвать
pg_archive_run_maintenance_proc()
вручную:
CALL archive.pg_archive_run_maintenance_proc();
F.33.3.1. Примеры #
Сначала создайте расширение. Оно требует, чтобы
pg_columnar
также был установлен, поэтому используйте
CASCADE
.
CREATE EXTENSION pg_archive CASCADE;
После этого вы можете захотеть включить фоновый рабочий процесс для архивирования таблиц в фоновом режиме. Это требует изменений в файле конфигурации.
shared_preload_libraries = 'pg_archive_bgw' pg_archive_bgw.dbname = 'postgres' pg_archive_bgw.role = 'postgres' pg_archive_bgw.interval = 3600
Изменения:
shared_preload_libraries
- фоновый рабочий процесс должен быть загружен при запуске сервера для регистрацииpg_archive_bgw.dbname
- установлено вpostgres
как база данных по умолчаниюроль
иинтервал
- это значения по умолчанию, но вы можете их изменитьзапустите как
postgres
пользователь (в производственной среде создайте отдельную роль для фонового рабочего процесса, не суперпользователь)запускать каждый час (3600 секунд)
Далее следуют дополнительные примеры. Все операции выполняются в
postgres
базе данных и
public
схеме. После каждого примера, данная
таблица должна быть зарегистрирована в pg_archive для дальнейшего архивирования.
Но если вы хотите, чтобы обслуживание выполнялось немедленно, выполните процедуру:
CALL pg_archive_run_maintenance_proc();
Или, вы можете захотеть принудительно преобразовать раздел. Это можно сделать с помощью другой процедуры (заметьте: она принимает имя таблицы раздела - не родителя):
CALL pg_archive_convert_partition_proc('public.partition_tbl_name');
Чтобы проверить, что таблицы архивированы, вы можете выполнить этот запрос:
SELECT c.relname, am.amname FROM pg_class c JOIN pg_am am ON c.relam = am.oid WHERE c.relname LIKE 'tbl_name%';
'tbl_name%'
в запросе должен быть заменен на реальное имя таблицы. Предположим, что секционированные таблицы имеют имя как у родительской таблицы плюс суффикс в конце.
Не стесняйтесь изменять границы разделов или максимальный возраст (параметр для
pg_archive_manage
), чтобы проверить, что таблицы
преобразуются.
Таблица для измерений температуры, разделенная по временной метке измерения. Используется в основном для аналитики, поэтому архивируйте её часто - установите максимальный возраст на 1 день.
CREATE TABLE measurements( temp numeric NOT NULL, ts timestamp NOT NULL ) PARTITION BY RANGE(ts); CREATE TABLE measurements_20240901 PARTITION OF measurements FOR VALUES FROM ('2024-09-01') TO ('2024-09-02'); CREATE TABLE measurements_20240902 PARTITION OF measurements FOR VALUES FROM ('2024-09-02') TO ('2024-09-03'); CREATE TABLE measurements_20240903 PARTITION OF measurements FOR VALUES FROM ('2024-09-03') TO ('2024-09-04'); SELECT pg_archive_manage('public.measurements', 'ts', '1 day');
Храните бронирования клиентов в секционированной таблице. Бронирования могут быть изменены в любое время, поэтому секции разделены по месяцам.
CREATE TABLE bookings( customer_id int NOT NULL, book_date date NOT NULL ) PARTITION BY RANGE(book_date); CREATE TABLE bookings_20240901 PARTITION OF bookings FOR VALUES FROM ('2024-09-01') TO ('2024-09-02'); CREATE TABLE bookings_20240902 PARTITION OF bookings FOR VALUES FROM ('2024-09-02') TO ('2024-09-03'); CREATE TABLE bookings_20240903 PARTITION OF bookings FOR VALUES FROM ('2024-09-03') TO ('2024-09-04'); SELECT pg_archive_manage('public.bookings', 'book_date', '1 year');
Используйте секционированную таблицу для хранения журналов микросервисов. Метки времени журналов предоставляются в виде UNIX-метки времени (в секундах).
CREATE TABLE logs( message text NOT NULL, service int NOT NULL, ts numeric NOT NULL ) PARTITION BY RANGE(ts); CREATE TABLE logs_202409 PARTITION OF logs FOR VALUES FROM (1725148800) TO (1727740800); CREATE TABLE logs_202410 PARTITION OF logs FOR VALUES FROM (1727740800) TO (1730419200); CREATE TABLE logs_202411 PARTITION OF logs FOR VALUES FROM (1730419200) TO (1733011200); SELECT pg_archive_manage('public.logs', 'ts', '1 month', p_epoch := 'seconds');
F.33.4. Функции, Процедуры и Таблицы #
Ниже приведено описание доступных функций, их аргументов
и столбцов в таблице pg_archive_config
:
F.33.4.1. pg_archive_manage()
#
CREATE FUNCTION @extschema@.pg_archive_manage( p_parent_table text , p_control text , p_max_age text , p_type text DEFAULT 'range' , p_epoch text DEFAULT 'none' , p_automatic_maintenance boolean DEFAULT true )
Функция регистрирует таблицу разделов для управления pg_archive.
p_parent_table
существующая секционированная таблица. ДОЛЖНА быть с указанием схемы, даже если находится в публичной схеме
p_control
name of a column that the partitioning will be based on. Must be of either a time- or integer-based type
p_max_age
либо временной интервал в формате типа PostgreSQL
INTERVAL
, либо целое значение, в зависимости от типа разбиения. Независимо от используемого типа разбиения, это значение должно быть указано как текст.
p_type
тип разбиения, используемый таблицей. В настоящее время поддерживаются только range и list. См. параметр
p_max_age
для особых условий, связанных с типом.
p_epoch
сообщает
pg_archive
, что управляющий столбец является целочисленным типом, но фактически представляет значение времени эпохи. Допустимые значения для этой опции:'seconds'
,'milliseconds'
,'nanoseconds'
и'none'
. Значение по умолчанию —'none'
. В дополнение к обычному индексу на управляющем столбце, обязательно создайте функциональный, основанный на времени индекс на управляющем столбце(to_timestamp(controlcolumn))
, чтобы это работало эффективно.
p_automatic_maintenance
указывает, управляется ли обслуживание автоматически, когда вызывается
pg_archive_run_maintenance_proc()
без параметра таблицы или фоновым рабочим процессом. По умолчаниюtrue
. Когда установлено вfalse
,pg_archive_run_maintenance_proc()
все еще может быть вызвана для отдельного набора разделов, передавая его в качестве параметра функции.
F.33.4.2. pg_archive_convert_partition()
#
CREATE PROCEDURE @extschema@.pg_archive_convert_partition_proc( p_partition text , p_access_method text DEFAULT 'columnar' , p_keep_indexes boolean DEFAULT true , p_reattach boolean DEFAULT false )
Функция может быть полезна, когда отдельный раздел необходимо
архивировать вручную. Обратите внимание, что вам нужно вызвать
pg_archive_manage()
для соответствующей
родительской таблицы, прежде чем ее разделы могут быть переданы в
pg_archive_convert_partition()
.
p_partition
спецификация раздела в формате
schema.name
.
p_access_method
метод доступа для использования архивированной таблицы. В настоящее время
columnar
(по умолчанию) является единственным поддерживаемым методом.
p_keep_indexes
логическое значение, указывающее, следует ли сохранять индексы в архивированной таблице
по умолчанию
true
p_reattach
логическое значение, указывающее, следует ли присоединить архивированную таблицу обратно к родительской таблице
по умолчанию
true
F.33.4.3. pg_archive_config
#
CREATE TABLE @extschema@.pg_archive_config ( parent_table text NOT NULL , control text NOT NULL , partition_type text NOT NULL , automatic_maintenance boolean NOT NULL DEFAULT true , max_age text NOT NULL , new_schema text , keep_indexes boolean NOT NULL DEFAULT true , reattach boolean NOT NULL DEFAULT true , access_method text NOT NULL DEFAULT 'columnar' , epoch text NOT NULL DEFAULT 'none' , maintenance_order int , keep_publication boolean NOT NULL DEFAULT false , maintenance_last_run timestamptz , CONSTRAINT pg_archive_config_parent_table_pkey PRIMARY KEY (parent_table) );
parent_table
родительская таблица набора разделов для управления
control
столбец, используемый в качестве контроля для ограничений разделения. Должен быть столбцом на основе времени или целым числом.
partition_type
тип разбиения. Должен быть одним из типов, упомянутых выше в документации
pg_archive_manage()
.
automatic_maintenance
флаг, указывающий, управляется ли обслуживание автоматически, когда
pg_archive_run_maintenance_proc()
вызывается без параметра таблицы или фоновым рабочим процессом.По умолчанию
true
.Когда установлено значение
false
,pg_archive_run_maintenance_proc()
все еще может быть вызвана для отдельного раздела, передавая его в качестве параметра функции.
max_age
text type value, который определяет, насколько старыми могут быть данные в дочернем разделе, прежде чем раздел будет архивирован.
new_schema
схема для перемещения архивированных разделов в рамках процесса архивирования.
NULL
(по умолчанию) означает, что разделы не изменяют свою схему после архивирования.
keep_indexes
логическое значение, указывающее, следует ли удалять индексы для архивированных таблиц.
По умолчанию
true
. Установка вfalse
означает, что pg_archive не будет пытаться воссоздать какие-либо индексы на архивированной таблице. Обратите внимание, что если таблица настроена на повторное присоединение архивированных разделов (см.reattach
ниже), PostgreSQL может автоматически воссоздать индексы, унаследованные от родительской таблицы. См. документацию PostgreSQL дляALTER TABLE ATTACH PARTITION
для получения дополнительной информации.
reattach
логическое значение, указывающее, должны ли разделы оставаться прикрепленными к родительской таблице после преобразования. Установка его в «false» означает, что разделы будут продолжать существовать как отдельные таблицы после архивации, т.е. будут отсоединены от родительской таблицы.
по умолчанию
true
access_method
метод доступа для использования при преобразовании разделов во время архивирования
значение по умолчанию и единственное в настоящее время поддерживаемое значение -
columnar
epoch
указывает, что таблица разделена по времени с использованием целочисленного значения эпохи вместо метки времени. См. описание соответствующего аргумента в
pg_archive_manage()
функции для получения дополнительной информации.по умолчанию
'none'
.
maintenance_order
целочисленное значение, определяющее порядок выполнения обслуживания наборов разделов. Наборы будут выполняться в порядке возрастания числового значения.
значение по умолчанию
NULL
. Все наборы разделов, установленные в NULL, будут выполняться после наборов разделов с определенным значением. Наборы разделовNULL
выполняются в неопределенном порядке.для наборов с подчастичными разделами дочерние таблицы по умолчанию наследуют порядок своих родительских таблиц. Дочерние родительские таблицы будут выполняться в логическом порядке, когда будет выполняться обслуживание их родительской таблицы, если оставить значение по умолчанию.
keep_publication
определяет, следует ли удалять архивированные разделы из любых публикаций, членами которых они могут быть.
по умолчанию
false
, что означает, что архивированные разделы удаляются из их публикаций.
maintenance_last_run
временная метка последнего успешного запуска обслуживания для этого набора разделов. Может быть полезно в качестве метрики мониторинга для обеспечения правильной работы обслуживания разделов.
F.33.5. Ограничения в использовании #
В рамках процедуры архивирования pg_archive должен скопировать данные раздела в новую таблицу, а затем обменять существующий раздел на новую архивированную версию (если только reattach
не настроен на false
для этой таблицы). Поскольку ALTER TABLE ... EXCHANGE PARTITION
в настоящее время не поддерживается PostgreSQL, это сводится либо к DROP TABLE
, либо к ALTER TABLE DETACH PARTITION
, за которым следует ALTER TABLE ATTACH PARTITION
.
Оба DROP TABLE
для раздела и
DETACH PARTITION
берут
ACCESS EXCLUSIVE
блокировку на родительской таблице, что
проблематично для загруженных таблиц. Хотя в PostgreSQL 14
была введена команда DETACH PARTITION CONCURRENTLY
для
решения этой конкретной проблемы, эта функциональность недоступна
для расширений, потому что
ALTER TABLE DETACH PARTITION CONCURRENTLY
должна
быть командой верхнего уровня и не может использоваться в хранимых процедурах.
См.
это
обсуждение на pgsql-general для получения дополнительной информации.
В результате pg_archive в настоящее время использует
DROP TABLE
для отсоединения раздела как единственный
жизнеспособный вариант. Мы осознаем проблемы, которые это может вызвать для загруженных,
часто изменяющихся таблиц, и ищем возможные обходные пути.