Автоматическое управление секциями

В этом документе описывается политика автоматического управления секциями и её использование в YMatrix.

В производственных средах данные часто секционируются по времени. YMatrix предоставляет несколько пользовательских функций (UDF) для управления секциями, позволяя администраторам вручную поддерживать секции в соответствии с требованиями — например, создавать одну секцию в день или каждые 8 часов.
Однако время является бесконечной размерностью. При создании секционированных таблиц администраторы обычно заранее создают секции только на ограниченный период в будущем, а затем периодически добавляют новые. Это увеличивает эксплуатационные издержки.

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

  1. Автоматическое создание и удаление секций
  2. Автоматическое разделение секций по умолчанию
  3. Пакетное создание секций
  4. Принудительное сохранение определённых исторических секций
  5. Настройка временных окон для выполнения автоматических задач

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

=# CREATE EXTENSION matrixts;

Используйте функцию set_policy(), чтобы назначить политику целевой таблице и включить автоматическое обслуживание секций.

В настоящее время поддерживаются три политики:

  1. auto_partitioning
  2. auto_splitting
  3. auto_partitioning_ex

Примечание!
Начиная с версии 5.0, YMatrix представляет политику auto_partitioning_ex. Используйте эту политику вместо auto_partitioning, чтобы воспользоваться расширенными возможностями, такими как пакетное создание секций, принудительное сохранение определённых исторических секций и настраиваемые временные окна операций.

1 Политики секционирования

1.1 auto_partitioning

Политика auto_partitioning включает автоматическое управление обычными секционированными таблицами и предоставляет две возможности автоматизации:

  1. Создание новых секций
  2. Очистка устаревших секций

Пример: создайте тестовую секционированную таблицу с именем metrics:

=# CREATE TABLE metrics(
   time timestamp with time zone,
   tag_id int,
   read float,
   write float
   )
   USING MARS3
   DISTRIBUTED BY (tag_id)
   ORDER BY (time,tag_id)
   PARTITION BY RANGE (time);

Назначьте таблице metrics политику автоматического секционирования auto_partitioning:

=# SELECT set_policy(
    'metrics'::regclass,
    'auto_partitioning'
);

Если требуется указание схемы, передайте параметр как 'schema_name.metrics'.

После установки политики используйте list_policy(), чтобы просмотреть её:

=# SELECT * FROM list_policy('metrics'::regclass);
 reloid | relname | class_id |    class_name     |   action    | seq | disabled |               check_func               |      check_args      |                    act_func                    |       act_args        | versi
on
--------+---------+----------+-------------------+-------------+-----+----------+----------------------------------------+----------------------+------------------------------------------------+-----------------------+------
---
  23361 | metrics |        2 | auto_partitioning | retention   |   1 | t        | matrixts_internal.apm_generic_expired  | {"after": "1 year"}  | matrixts_internal.apm_generic_drop_partition   | {}                    | 1.0
  23361 | metrics |        2 | auto_partitioning | auto_create |   2 | f        | matrixts_internal.apm_generic_incoming | {"before": "3 days"} | matrixts_internal.apm_generic_append_partition | {"period": "8 hours"} | 1.0
(2 rows)

Как показано, политика auto_partitioning включает два действия:

  1. retention: удаление устаревших секций
  2. auto_create: создание новых секций

Действие retention использует проверочный аргумент {"after": "1 year"}, что означает, что любая секция старше одного года будет удалена.
Действие auto_create проверяет, должна ли быть создана новая секция, используя значение {"before": "3 days"} — то есть за три дня до наступления — и создаёт секции с временным интервалом {"period": "8 hours"}. Это значения по умолчанию для политики auto_partitioning.

Чтобы изменить эти параметры, вызовите set_policy_action().

Пример: измените retention, чтобы удалять секции после трёх месяцев; измените auto_create, чтобы просматривать вперёд на 2 дня и создавать суточные секции:

=# SELECT set_policy_action(
    'metrics'::regclass,
    'retention',
    '3 months'
);

=# SELECT set_policy_action(
    'metrics'::regclass,
    'auto_create',
    '{
        "before": "2 days",
        "period": "1 day"
    }'
);

Примечание!
Для действий с одним параметром укажите целевое значение непосредственно в виде строки (например, '3 months'). Для действий с несколькими параметрами используйте JSON-объект для указания всех аргументов (например, '{"before": "2 days", "period": "1 day"}').

1.2 auto_splitting

Политика auto_splitting применяется к секционированным таблицам, содержащим секцию по умолчанию. Она автоматически разделяет секцию по умолчанию на основе времени.

Пример: создайте секционированную таблицу и определите секцию по умолчанию:

=# CREATE TABLE metrics(
   time timestamp with time zone,
   tag_id int,
   read float,
   write float
   )
   USING MARS3
   DISTRIBUTED BY (tag_id)
   ORDER BY (time,tag_id)
   PARTITION BY RANGE (time);

=# CREATE TABLE metrics_others PARTITION OF metrics DEFAULT;

Примените политику auto_splitting:

=# SELECT set_policy(
    'metrics'::regclass,
    'auto_splitting'
);

Просмотрите политику:

=# SELECT * FROM list_policy('metrics'::regclass);
 reloid | relname | class_id |   class_name   |   action   | seq | disabled |                check_func                |        check_args        |                       act_func                        |       act_args        | version
--------+---------+----------+----------------+------------+-----+----------+------------------------------------------+--------------------------+-------------------------------------------------------+-----------------------+---------
  17798 | metrics |        1 | auto_splitting | retention  |   1 | t        | matrixts_internal.apm_generic_expired    | {"after": "1 year"}      | matrixts_internal.apm_generic_drop_partition          | {}                    | 1.0
  17798 | metrics |        1 | auto_splitting | auto_split |   2 | f        | matrixts_internal.apm_generic_older_than | {"age": "1 month 2days"} | matrixts_internal.apm_generic_split_default_partition | {"period": "1 month"} | 1.0
(2 rows)

Политика auto_splitting включает два действия: retention (удаление устаревших секций) и auto_split (автоматическое разделение секции по умолчанию).

Здесь {"age": "1 month 2days"} означает, что разделение запускается, когда самые старые данные в секции по умолчанию старше 1 месяца и 2 дней.
{"period": "1 month"} указывает, что каждая полученная секция покрывает интервал в 1 месяц.

1.3 auto_partitioning_ex

Политика auto_partitioning_ex расширяет функциональность auto_partitioning, предлагая расширенные возможности управления секциями:

  1. Пакетное создание секций
  2. Принудительное сохранение определённых исторических секций
  3. Настраиваемые временные окна для автоматических операций

Эти функции подробно описаны в приведённых ниже примерах.

Создайте секционированную таблицу и определите специальную секцию:

=# CREATE TABLE metrics(
    time timestamp with time zone,
    tag_id int,
    read float,
    write float
    )
    USING MARS3
    DISTRIBUTED BY (tag_id)
    ORDER BY (time,tag_id)
    PARTITION BY RANGE (time);

=# CREATE TABLE metrics_invalid_apmtrap PARTITION OF metrics FOR VALUES FROM ('-infinity') TO ('2023-01-01');

Установите политику auto_partitioning_ex:

=# SELECT set_policy(
    'metrics'::regclass,
    'auto_partitioning_ex'
);

Просмотрите политику:

=# SELECT * FROM list_policy('metrics'::regclass);
reloid | relname | class_id |      class_name      |   action    | seq | disabled |                check_func                 |                                                               check_args
                   |                    act_func                    |       act_args        | version
--------+---------+----------+----------------------+-------------+-----+----------+-------------------------------------------+---------------------------------------------------------------------------------------------------------------------
-------------------+------------------------------------------------+-----------------------+---------
  34917 | metrics |        4 | auto_partitioning_ex | retention   |   1 | t        | matrixts_internal.apm_generic_expired     | {"after": "1 year"}
                   | matrixts_internal.apm_generic_drop_partition   | {}                    | 1.0
  34917 | metrics |        4 | auto_partitioning_ex | auto_create |   2 | f        | matrixts_internal.apm_generic_incoming_ex | {"before": "3 days", "period": "8 hours", "end_time": "00:00:00", "batch_size": "0", "start_time": "00:00:00", "stor
age_type": "heap"} | matrixts_internal.apm_generic_append_partition | {"period": "8 hours"} | 1.0
(2 rows)

1. Пакетное создание секций

Из вывода видно, что действие auto_create в рамках auto_partitioning_ex имеет параметры "before": "3 days" и "period": "8 hours". Это означает, что автоматизированная система обеспечит предварительное создание всех секций на следующие 3 дня, при этом каждая из них будет покрывать интервал в 8 часов. Например, если текущее время — 1 марта, 00:01, система запустит создание секций и обеспечит готовность всех секций до 4 марта, 00:00. В момент 4 марта, 00:00 система начнёт создавать следующую 8-часовую секцию (4 марта, 00:00–08:00). Такой подход гарантирует, что политика auto_partitioning_ex всегда заранее подготовит секции на ближайшие 3 дня.

Однако другие параллельные задачи могут удерживать блокировки таблицы, что вызывает конфликты блокировок при попытке автоматической системы создать секции. Чтобы уменьшить частоту таких конфликтов, политика auto_partitioning_ex вводит опцию batch_size.

Установите её с помощью следующей команды:

=# SELECT public.set_policy_action('metrics'::regclass, 'auto_create', '{ "batch_size": "4" }');

Это означает, что всякий раз, когда нужно создать новую секцию, система одновременно создаст ещё 4 будущие секции. Таким образом, при создании секции 4 марта, 00:00–08:00 в 1 марта, 00:01, будут также созданы следующие четыре 8-часовые секции: 4 марта, 08:00–16:00; 4 марта, 16:00–24:00; 5 марта, 00:00–08:00; и 5 марта, 08:00–16:00.
Это позволяет избежать повторного запуска создания секций между 1 и 4 марта, тем самым снижая конкуренцию за блокировки.

  • Значение по умолчанию для batch_size0, что означает отсутствие пакетного режима — поведение идентично auto_partitioning.
  • Максимальное значение batch_size7.

Примечание!
Хотя пакетное создание уменьшает частоту конфликтов блокировок (например, с ежедневного до раз в несколько дней), оно не может полностью устранить конфликты блокировок при выполнении автоматической задачей DDL-операций. Это ограничение обусловлено базовыми механизмами параллелизма в базах данных.
Поэтому необходимо обеспечить надлежащий мониторинг запросов, блокировок и выполнения автоматического управления секциями.

2. Принудительное сохранение определённых исторических секций

Как показано выше, мы создали секцию с именем metrics_invalid_apmtrap. Когда включена функция retention (автоматическое удаление секций) в рамках auto_partitioning_ex, любая секция, имя которой содержит строку apmtrap (например, metrics_invalid_apmtrap), не будет удалена, даже если она соответствует условию истечения срока. Это обеспечивает постоянное хранение назначенных исторических секций.

Эта функция предназначена для реализации «ловушки» — секции, которая собирает данные вне диапазона (например, метки времени вроде 1970-01-01). Такая ловушка поглощает недопустимые данные, которые в противном случае попали бы в секцию по умолчанию, предотвращая её быстрый рост. Кроме того, поскольку эта секция не участвует в запросах или DDL-операциях, это помогает сохранить производительность запросов.

3. Настройка временных окон для автоматических операций с секциями

Из предыдущего результата list_policy() обратите внимание на параметры start_time и end_time в поле check_args. Эти параметры контролируют временное окно, в течение которого могут выполняться задачи автоматического управления секциями, помогая избежать создания секций в часы пиковой нагрузки.

Например:

  • "start_time": "01:00:00", "end_time": "04:00:00" разрешает операции ежедневно с 1:00 до 4:00.

  • "start_time": "22:00:00", "end_time": "03:00:00" разрешает операции с 22:00 до 3:00 следующего дня.

  • Значение по умолчанию для обоих полей — "00:00:00", что означает отсутствие временных ограничений — операции разрешены в любое время.

Пример:

SELECT public.set_policy_action('table_name'::regclass, 'auto_create', '{ "start_time": "00:00:00", "end_time": "04:00:00" }');

Примечание!
Временное окно должно быть не менее 1 часа. Интервал проверки по умолчанию для автоматического управления секциями составляет 1 час. Окно короче 1 часа может пропустить момент запуска.
Достижение end_time не приводит к немедленному завершению выполняющихся операций. Любая запущенная задача продолжается до завершения. end_time лишь предотвращает начало новых проверок после этого момента — он не принудительно останавливает выполняющиеся задачи. Поэтому при установке end_time следует предусмотреть достаточное резервное время до следующего периода пиковой нагрузки.

2 Управление состоянием действий

Из вывода list_policy() обратите внимание на столбец disabled. Этот столбец управляет активностью действия политики. По умолчанию, независимо от типа политики, действие retention отключено.

Чтобы включить действие, используйте enable_policy_action():

=# SELECT enable_policy_action('metrics'::regclass, 'retention');

Чтобы отключить действие, используйте disable_policy_action():

=# SELECT disable_policy_action('metrics', 'auto_split');

3 Удаление политики

Используйте drop_policy(), чтобы удалить политику из секционированной таблицы:

=# SELECT drop_policy('metrics'::regclass);

Примечание!
Каждая секционированная таблица может иметь только одну политику секционирования. Поэтому для удаления политики достаточно указать только имя таблицы.

4 Мониторинг журналов

4.1 apm_operation_log

Таблица apm_operation_log регистрирует каждую операцию пользователя, выполненную при настройке APM. Пример:

=# SELECT username = CURRENT_USER, relname, class_id, class_name, action, operation, mod_field, old_val, new_val
FROM matrixts_internal.apm_operation_log ORDER BY ts;
 ?column? |      relname       | class_id | class_name |   action   | operation | mod_field  |        old_val         |        new_val         
----------+--------------------+----------+------------+------------+-----------+------------+------------------------+------------------------
 t        | apm_test.split_set |          |            | test_split | add       | check_args |                        | {"age": "1 month"}
 t        | apm_test.split_set |          |            | test_split | add       | act_args   |                        | {"period": "2 weeks"}
 t        | apm_test.split_set |          |            | test_split | mod       | act_args   | {"period": "2 weeks"}  | {"period": "12 hours"}
 t        | apm_test.split_set |          |            | test_split | mod       | check_args | {"age": "1 month"}     | {"age": "15 days"}
 t        | apm_test.split_set |          |            | test_split | mod       | check_args | {"age": "15 days"}     | {"age": "5 days"}
 t        | apm_test.split_set |          |            | test_split | mod       | act_args   | {"period": "12 hours"} | {"period": "2 days"}
 t        | apm_test.split_set |          |            | test_split | drop      |            |                        | 
 t        | apm_test.split_set |          |            | test_split | add       | check_args |                        | {"age": "10 days"}
 t        | apm_test.split_set |          |            | test_split | add       | act_args   |                        | {"period": "1 hour"}
(9 rows)

4.2 apm_action_log

Таблица apm_action_log регистрирует каждую операцию автоматического секционирования, выполняемую фоновым процессом APM. Пример:

=# (select * from matrixts_internal.apm_action_log order by ts limit 6) union all (select * from matrixts_internal.apm_action_log order by ts desc limit 6) order by 1;
             ts             |  pid  | reloid |         relname          |      nspname       | class_id |    class_name     |   action    |               check_func               |      check_args      |                    act_func
      |      act_args       |  state  |      message      | details | addopt |  client
----------------------------+-------+--------+--------------------------+--------------------+----------+-------------------+-------------+----------------------------------------+----------------------+------------------------------------------
------+---------------------+---------+-------------------+---------+--------+----------
 2022-11-18 15:48:45.963264 | 15776 |  18360 | mx_query_execute_history | matrixmgr_internal |        2 | auto_partitioning | auto_create | matrixts_internal.apm_generic_incoming | {"before": "3 days"} | matrixts_internal.apm_generic_append_part
ition | {"period": "1 day"} | START   | action start      |         |        | schedule
 2022-11-18 15:48:46.165418 | 15776 |  18360 | mx_query_execute_history | matrixmgr_internal |        2 | auto_partitioning | auto_create | matrixts_internal.apm_generic_incoming | {"before": "3 days"} | matrixts_internal.apm_generic_append_part
ition | {"period": "1 day"} | SUCCESS | do action success |         |        | schedule
 2022-11-18 15:48:46.172096 | 15776 |  18373 | mx_query_usage_history   | matrixmgr_internal |        2 | auto_partitioning | auto_create | matrixts_internal.apm_generic_incoming | {"before": "3 days"} | matrixts_internal.apm_generic_append_part
ition | {"period": "1 day"} | START   | action start      |         |        | schedule
 2022-11-18 15:48:46.332781 | 15776 |  18373 | mx_query_usage_history   | matrixmgr_internal |        2 | auto_partitioning | auto_create | matrixts_internal.apm_generic_incoming | {"before": "3 days"} | matrixts_internal.apm_generic_append_part
ition | {"period": "1 day"} | SUCCESS | do action success |         |        | schedule
 2022-11-19 00:48:45.992494 | 24930 |  18360 | mx_query_execute_history | matrixmgr_internal |        2 | auto_partitioning | auto_create | matrixts_internal.apm_generic_incoming | {"before": "3 days"} | matrixts_internal.apm_generic_append_part
ition | {"period": "1 day"} | START   | action start      |         |        | schedule
 2022-11-19 00:48:46.064604 | 24930 |  18360 | mx_query_execute_history | matrixmgr_internal |        2 | auto_partitioning | auto_create | matrixts_internal.apm_generic_incoming | {"before": "3 days"} | matrixts_internal.apm_generic_append_part
ition | {"period": "1 day"} | SUCCESS | do action success |         |        | schedule
 2022-11-21 00:48:47.708846 | 14091 |  18373 | mx_query_usage_history   | matrixmgr_internal |        2 | auto_partitioning | auto_create | matrixts_internal.apm_generic_incoming | {"before": "3 days"} | matrixts_internal.apm_generic_append_part
ition | {"period": "1 day"} | START   | action start      |         |        | schedule
 2022-11-21 00:48:47.812423 | 14091 |  18373 | mx_query_usage_history   | matrixmgr_internal |        2 | auto_partitioning | auto_create | matrixts_internal.apm_generic_incoming | {"before": "3 days"} | matrixts_internal.apm_generic_append_part
ition | {"period": "1 day"} | SUCCESS | do action success |         |        | schedule
 2022-11-22 00:48:46.552925 |  8539 |  18360 | mx_query_execute_history | matrixmgr_internal |        2 | auto_partitioning | auto_create | matrixts_internal.apm_generic_incoming | {"before": "3 days"} | matrixts_internal.apm_generic_append_part
ition | {"period": "1 day"} | START   | action start      |         |        | schedule
 2022-11-22 00:48:53.25854  |  8539 |  18360 | mx_query_execute_history | matrixmgr_internal |        2 | auto_partitioning | auto_create | matrixts_internal.apm_generic_incoming | {"before": "3 days"} | matrixts_internal.apm_generic_append_part
ition | {"period": "1 day"} | SUCCESS | do action success |         |        | schedule
 2022-11-22 00:48:53.261857 |  8539 |  18373 | mx_query_usage_history   | matrixmgr_internal |        2 | auto_partitioning | auto_create | matrixts_internal.apm_generic_incoming | {"before": "3 days"} | matrixts_internal.apm_generic_append_part
ition | {"period": "1 day"} | START   | action start      |         |        | schedule
 2022-11-22 00:48:55.625125 |  8539 |  18373 | mx_query_usage_history   | matrixmgr_internal |        2 | auto_partitioning | auto_create | matrixts_internal.apm_generic_incoming | {"before": "3 days"} | matrixts_internal.apm_generic_append_part
ition | {"period": "1 day"} | SUCCESS | do action success |         |        | schedule
(12 rows)