Automated partition management

This document introduces the automated partition management policies and usage in YMatrix.

In production environments, data partitioning is often done according to time. YMatrix provides some UDFs (User Defined Functions) used to manage partitions, and you can manually maintain partitions according to your needs. For example: one partition every day, one partition every 8 hours, etc.
But time is an infinitely extended dimension. When creating partition tables, administrators usually just create partitions in the future period in advance, and then regularly add new time period partitions. This undoubtedly increases operation and maintenance costs.

Automated partition management is to automate the work of manually maintaining partitions, thereby reducing the cost of administrators to maintain databases. include:

  1. Automatic partition creation and deletion
  2. Default partitioning automatically
  3. Bulk partition creation
  4. Force the preservation of specific historical partitions
  5. Customize the automatic partition operation period

The automated partition management feature is included in the matrixts extension, so first create the matrixts extension:

=# CREATE EXTENSION matrixts;

By calling set_policy, setting policies for the target table, partition maintenance automation is achieved:

Currently, there are 3 strategies:

  1. auto_partitioning
  2. auto_splitting
  3. auto_partitioning_ex

Notes!
Starting from version 5.0, YMatrix has added the auto_partitioning_ex policy. It is recommended to use this policy instead of auto_partitioning to implement advanced features such as batch creation of partitions, forced preservation of specific historical partitions, and customizing automatic partition operation periods.

1 Partition Policy

1.1 auto_partitioning

The auto_partitioning policy is applied to the automated management of ordinary partition tables, and implements the following 2 automation functions:

  1. New partition creation
  2. Expired partition cleaning

Example, create a test partition table metrics, as follows:

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

Create an auto_partitioning automatic partitioning policy for the metrics table:

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

If you need to carry mode information, just pass the parameter schema_name.table_name.

After setting the policy, call list_policy to view the policy:

=# 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 |        2 | auto_partitioning | retention   |   1 | t        | matrixts_internal.apm_generic_expired  | {"after": "1 year"}  | matrixts_internal.apm_generic_drop_partition   | {}                    | 1.0
  17798 | 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)

As you can see, auto_partitioning contains two operations in total:

  1. Retention: Delete expired partitions
  2. auto_create: new partition creation

The detection parameter of retention is {"after": "1 year"}, which means detecting whether the partition has been more than one year and then deleting it. The detection parameter of auto_create is {"before": "3 days"}, which means to check whether a new partition needs to be created 3 days in advance; the execution parameter is {"period": "8 hours"}, which means to create a new partition with a span of 8 hours. This is the default setting for the auto_partitioning policy.

If you want to adjust these parameters, you need to call set_policy_action.

Example, adjust retention to automatically delete after 3 months; auto_create is adjusted 2 days in advance, with a time span of 1 day:

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

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

Notes!
For action with only one parameter, just write the target value string directly, such as retention. For actions containing multiple parameters, the target value needs to be completed through JSON splicing. Such as auto_create.

1.2 auto_splitting

The auto_splitting policy implements the default partition cutting operation for partition tables containing default partitions.

Example, create a partition table and create a default partition for it:

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

=# CREATE TABLE metrics_others PARTITION OF metrics DEFAULT;

Set the auto_splitting policy:

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

View the policy:

=# 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)

As you can see, the auto_splitting policy contains 2 operations, expired partition deletion retention and default partition automatic cutting auto_split.

Among them, {"age": "1 month 2days"} means that the oldest data in the default partition is earlier than January 2 days ago, and the current time is cut. {"period": "1 month"} means that the partition granularity after cutting is 1 month.

1.3 auto_partitioning_ex

The auto_partitioning_ex policy is a partitioning policy that upgrades functions based on auto_partitioning. It contains some advanced management operations on partition tables:

  1. Bulk partition creation
  2. Force the preservation of specific historical partitions
  3. Customize automatic partitioning working period

The above operations will be described in detail in the following examples.

Create a partition table and create an apmtrap partition for it:

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

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

Set the auto_partitioning_ex policy:

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

View the policy:

=# SELECT * FROM list_policy('metrics');
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. Bulk partition creation From the table, you can see that the auto_partitioning policy has been set "before": "3 days", "period": "8 hours", that is, the automatic partition management operation will create all partitions in the next 3 days of this table in advance, and the size of each partition is 8 hours. For example, if the current time is March 1 0:00, then automatic partition creation is triggered, and all partitions from March 1 0:00 to 8:00 to March 4 0:00 to 8:00. By 8:01 on March 1, the automatic partition management operation will start creating a new 8-hour partition, that is, the partition from 8:00 to 16:00 on March 4. The above design of the auto_partitioning strategy can ensure that all partitions within the next 3 days will always be ready in advance. However, since other tasks may occupy this table, the SQL statement that triggers the partition creation by the automatic partition management operation may compete with other tasks for locks. To reduce the number of lock competitions, the batch_size option is added in auto_partitioning_ex. Settings with the following statement:
    =# SELECT public.set_policy_action('metrics'::regclass, 'auto_create', '{ "batch_size": "4" }');

    This means that once the automatic partition management operation starts creating a partition, more future partitions of batch_size will be created. Therefore, when the partitions from 0:00 to 8:00 on March 4 will be created at 0:00 to 8:00 on March 4, this time it will create four future partitions at one time, from 0:00 to 8:00on March 4,8:00 to 16:00,16:00 to 24:00, and0:00 to 8:00` on March 5. This avoids triggering partition creation again between March 1 and March 4, reducing the number of times of lock competition.

  • The default value of batch_size is 0, which means that batch creation is not performed. At this time, the behavior of auto_partitioning_ex is consistent with auto_partitioning.
  • The maximum value of batch_size is 100.

Notes!
Although the batch creation function can reduce the frequency of lock competition from once a day to once a few days, once the automatic partition management operation executes specific SQL commands, it still cannot fundamentally avoid lock competition with other SQL commands. This is determined by the working principle of the database itself.
Therefore, from the perspective of database usage, still needs to set necessary monitoring and alarms for query and lock, automatic partition management operations, etc.

  1. Force the preservation of specific historical partitions As you can see from the table, we have created the apmtrap partition. This means that when you enable the automatic partition retention function of auto_partitioning/auto_partitioning_ex, the partition name contains the apmtrap string (such as `"sss_amptrap_sss""), and the partition will not be deleted even if it has met the recycling conditions, thus achieving permanent retention of these historical partitions.
    This feature is designed to maintain a "trap" partition that receives data outside the regular time range (such as 1970-01-01). This trap partition will swallow useless data for the default partition, thereby suppressing the rapid growth of the default partition. At the same time, the trap partition will not participate in query and DDL operations, protecting the query performance of the table.

  2. Customize automatic partitioning working period From the above list_policy result, you can see "end_time": "00:00:00" and "start_time": "00:00:00". In fact, the start_time / end_time parameter is used to control the period of automatic partition management, thereby avoiding creating partitions during busy business periods. For example, start_time = 01:00:00, end_time = 04:00:00 means that automatic partition management is allowed from 1:00 to 4:00 am every day. For example, start_time = 22:00:00, end_time = 03:00:00 means that automatic partition management is allowed from 22:00 to 3:00 am every night.

  • The default value is start_time = 00:00:00, end_time = 00:00:00. The same timestamp means no restrictions, that is, work is allowed 24 hours a day.
    SELECT public.set_policy_action('table_name'::regclass, 'auto_create', '{ "start_time": "00:00:00", "end_time": "04:00:00" }');

    Notes!
    The set time range should not be less than 1 hour, because the check period for automatic partition management is 1 hour by default. If the start and end time interval is less than 1 hour, it is very likely that the trigger opportunity will be missed. Arriving at the end_time deadline does not mean that the partition processing will end immediately at this time. The triggered automatic partition management work will continue until it is completed. end_time can only ensure that after this time, there will be no new round of automatic partition management checks to be triggered, but the automatic partition management work that has been triggered will not be forced to end. Therefore, when setting the end_time parameter, you need to leave enough buffering time for the upcoming business peak.

2 Operation status settings

From the above list_policy result you will notice that there is a column called disabled. This column is used to set the operation status. No matter which strategy currently exists, the status of the retention operation is disabled.

To enable this operation, call enable_policy_action:

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

To disable an action, call disable_policy_action:

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

3 Delete Policy

drop_policy is the partition table deletion policy:

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

Notes!
Each partition table can only set one partition policy, so the deletion policy only provides the partition table name.

4 Log Monitoring

4.1 apm_operation_log

apm_operation_log records each operation history of the user's configuration of APM. Examples are as follows:

=# 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 records the history of automatic partition operation in the APM background. Examples are as follows:

=# (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)