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

В этом документе описываются политики и использование автоматического управления секциями в 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.table_name.

После установки политики вызовите 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"}, что означает проверку необходимости создания новой секции за 3 дня до наступления срока; параметр выполнения — {"period": "8 hours"}, что означает создание новой секции продолжительностью 8 часов. Это значение по умолчанию для политики auto_partitioning.

Если вы хотите изменить эти параметры, необходимо вызвать set_policy_action.

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

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

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

Примечание!
Для действий с одним параметром достаточно указать строку целевого значения напрямую, например retention. Для действий с несколькими параметрами целевое значение должно быть передано в виде JSON-строки. Например, auto_create.

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"} означает, что самые старые данные в секции по умолчанию находятся ранее чем 2 января плюс два дня назад от текущего времени, и в этот момент происходит разрезание. {"period": "1 month"} означает, что после разрезания шаг секционирования составляет 1 месяц.

1.3 auto_partitioning_ex

Политика auto_partitioning_ex представляет собой усовершенствованную версию политики auto_partitioning, расширяющую функциональность. Она включает некоторые расширенные операции управления секционированными таблицами:

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

Вышеуказанные операции будут подробно описаны в следующих примерах.

Создадим секционированную таблицу и создадим для неё секцию apmtrap:

=# 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_partitioning установлено значение "before": "3 days", "period": "8 hours", то есть операция автоматического управления секциями заранее создаст все секции этой таблицы на следующие 3 дней, причём размер каждой секции составляет 8 часов. Например, если текущее время — March 1 0:00, то при запуске автоматического создания секций будут созданы все секции с March 1 0:00 to 8:00 по March 4 0:00 to 8:00. К 8:01 1 марта операция автоматического управления начнёт создавать новую 8-часовую секцию, то есть секцию с 8:00 до 16:00 4 марта. Такой подход в стратегии auto_partitioning гарантирует, что все секции на ближайшие 3 дня всегда будут подготовлены заранее. Однако, поскольку другие задачи могут использовать эту таблицу, SQL-запрос, запускающий создание секций, может конкурировать с другими задачами за блокировки. Чтобы снизить частоту конфликтов блокировок, в batch_size добавлена опция auto_partitioning_ex. Установка выполняется следующей командой:

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

Это означает, что как только операция автоматического управления начнёт создавать секцию, дополнительно будут созданы ещё batch_size будущих секций. Таким образом, когда настанет время создания секции с 0:00 до 8:00 4 марта, будет сразу создано четыре будущие секции: с 0:00 до 8:00on March 4,с 8:00 до 16:00,с 16:00 до 24:00, andс 0:00 до 8:00` 5 марта. Это позволяет избежать повторного запуска создания секций в период с 1 по 4 марта, снижая количество конфликтов блокировок.

  • Значение batch_size по умолчанию — 0, что означает отсутствие массового создания. В этом случае поведение auto_partitioning_ex совпадает с auto_partitioning.
  • Максимальное значение batch_size — 100.

Примечание!
Хотя функция массового создания может снизить частоту конфликтов блокировок с одного раза в день до одного раза в несколько дней, всё же невозможно полностью избежать конфликта блокировок с другими SQL-командами при выполнении конкретных команд автоматическим управлением секциями. Это определяется принципом работы самой СУБД.
Поэтому с точки зрения использования базы данных по-прежнему необходимо настраивать соответствующий мониторинг и оповещения для запросов, блокировок, операций автоматического управления секциями и т.д.

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

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

  1. Настройка рабочего периода автоматического секционирования

Из результата list_policy выше можно увидеть "end_time": "00:00:00" and "start_time": "00:00:00". Фактически, параметры start_time / end_time используются для контроля периода автоматического управления секциями, позволяя избежать создания секций в часы пиковой нагрузки. Например, 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 утра.

  • Значение по умолчанию — start_time = 00:00:00, end_time = 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)