可以通过以下操作管理分区:
1 - 删除分区
使用
DROP_PARTITIONS
函数删除给定表的一个或多个分区键。可以指定单个分区键或分区键范围。
例如,对新表进行分区中显示的表按列 order_date
进行分区:
=> CREATE TABLE public.store_orders
(
order_no int,
order_date timestamp NOT NULL,
shipper varchar(20),
ship_date date
)
PARTITION BY YEAR(order_date);
鉴于此表定义,Vertica 会为每个唯一的 order_date
年份(在本例中为 2017、2016、2015 和 2014 年)创建一个分区键,并相应地将数据划分到不同的 ROS 容器中。
以下 DROP_PARTITIONS
语句从表 store_orders
中删除与分区键 2014 关联的所有订单记录:
=> SELECT DROP_PARTITIONS ('store_orders', 2014, 2014);
Partition dropped
拆分分区组
如果表 partition 子句包括 GROUP BY
子句,则分区将按其分区组键在 ROS 中合并。 DROP_PARTITIONS
随后可以指定给定分区组内或跨多个分区组的分区键范围。无论哪种情况,删除操作都要求 Vertica 拆分存储这些分区的 ROS 容器。为此,该函数的 force_split
参数必须设置为 true。
例如,上面显示的 store_orders
表可以使用 GROUP BY
子句重新分区,如下所示:
=> ALTER TABLE store_orders
PARTITION BY order_date::DATE GROUP BY DATE_TRUNC('year', (order_date)::DATE) REORGANIZE;
由于之前删除了 2014 年的所有订单记录,order_date
值现在跨越三个年份(2017 年、2016 年和 2015 年)。因此,Tuple Mover 为每年创建三个分区组键,并为每个组指定一个或多个 ROS 容器。然后,它将 store_orders
分区合并到相应的组中。
以下 DROP_PARTITIONS
语句指定删除跨越两个年份(2014 年和 2015 年)的订单日期:
=> SELECT DROP_PARTITIONS('store_orders', '2015-05-30', '2016-01-16', 'true');
Partition dropped
删除操作要求 Vertica 从两个分区组(2015 和 2016)删除分区。这些组至少跨越两个 ROS 容器,必须拆分这些容器才能移除目标分区。因此,将函数的 force_split
参数设置为 true。
调度分区删除
如果硬件具有固定的磁盘空间,则可能需要配置一个定期执行的进程,以便通过删除分区来迁出旧数据。
例如,如果空间只够将数据存储固定的天数,请将 Vertica 配置为删除最旧的分区键。为此,请创建一个基于时间的作业调度程序(例如 cron
),以计划在低负载期间删除分区键。
如果数据输入速率具有峰值和谷值,则可以使用以下两种技术来管理分区键删除方式:
-
设置一个定期(每天)检查磁盘空间的进程。如果已用磁盘空间百分比超出特定阈值(例如 80%),则删除最旧的分区键。
-
在分区中添加一个可根据行计数等指标递增的假列。例如,每次行计数增加 100 行时,该列可能会递增。设置一个定期(每天)查询此列的进程。如果新列中的值超出特定阈值(例如 100),请删除最旧的分区键,并将该列的值设置回 0。
表锁定
DROP_PARTITIONS
会在目标表上获取一个独占的 O 锁,以阻止可能会影响表数据的任何 DML 操作(DELETE
、UPDATE
、INSERT
或 COPY
)。该锁还会阻止在 SERIALIZABLE 隔离级别发出的 SELECT
语句。
如果操作无法在目标表上获取 O lock,Vertica 将尝试关闭该表上运行的任何内部 tuple mover 会话。如果成功,则可以继续操作。在用户会话中运行的显式 Tuple Mover 操作不会关闭。如果显式 Tuple Mover 操作在表上运行,则该操作仅在 Tuple Mover 操作完成后继续。
2 - 存档分区
可以使用 Vertica 函数
MOVE_PARTITIONS_TO_TABLE
在表之间移动分区。此函数对于在下列过程中存档旧分区非常有用:
-
标识要存档的分区,并使用
MOVE_PARTITIONS_TO_TABLE
将其移动到临时暂存表。
可以随时还原已存档的分区。
将分区移动到临时表
存档历史数据的方法是标识要从表中移除的分区。然后,将每个分区(或分区组)移动到临时表。
在调用 MOVE_PARTITIONS_TO_TABLE
之前:
- 刷新所有过时投影。
以下建议适用于临时表:
-
为了方便备份过程,为每个存档操作的临时表创建唯一架构。
-
为临时表指定新名称。这可确保它们不包含先前移动操作中的分区。
如果该表不存在,Vertica 将根据源表的定义,通过调用CREATE TABLE
包含LIKE
和INCLUDING PROJECTIONS
子句来创建一个表。该新表会从源表中继承所有权。有关详细信息,请参阅复制表。 -
使用能够让其他用户轻松标识分区内容的临时名称。例如,如果表按日期分区,则使用指定日期或日期范围的名称。
在以下示例中,MOVE_PARTITIONS_TO_TABLE
指定将单个分区移动到临时表 partn_backup.tradfes_200801
。
=> SELECT MOVE_PARTITIONS_TO_TABLE (
'prod_trades',
'200801',
'200801',
'partn_backup.trades_200801');
MOVE_PARTITIONS_TO_TABLE
-------------------------------------------------
1 distinct partition values moved at epoch 15.
(1 row)
备份临时表。
在创建临时表后,可以使用
vbr
配置文件通过对象级备份来存档它。有关详细信息,请参阅备份和还原数据库。
重要
Vertica 建议在执行对象级备份之前先执行完整数据库备份,以防数据丢失。对象级备份只能还原为原始数据库。删除临时表
在备份完成后,可以按删除表中所述删除临时表。
还原已存档分区
您可以还原之前移至中间表、存档为对象级别备份后删除的分区。
注意
还原已存档分区要求原始表定义在分区被存档和删除后保持不变。如果表定义发生更改,则可以使用 INSERT...SELECT 语句还原已存档分区,此处不做介绍。还原已存档分区的步骤如下:
-
还原在移动一个或多个待存档分区时所保存的中间表的备份(请参阅存档分区)。
-
将还原后的分区从中间表移至原始表。
-
删除中间表。
3 - 交换分区
SWAP_PARTITIONS_BETWEEN_TABLES 将 DROP_PARTITIONS 和 MOVE_PARTITIONS_TO_TABLE 的操作合并为单个事务。如果定期将已分区数据从一个表加载到另一个表,并且需要刷新第二个表中的分区,则 SWAP_PARTITIONS_BETWEEN_TABLES 很有用。
例如,您可能具有一个按日期分区的收入表,而且经常将数据从临时表移动到该表中。临时表有时包含目标表中已有日期的数据。在这种情况下,首先必须从目标表中删除这些日期的分区,然后将其替换为临时表中的相应分区。可以通过调用一次 SWAP_PARTITIONS_BETWEEN_TABLES 来完成这两个任务。
通过将删除和移动操作包装在单个事务中,SWAP_PARTITIONS_BETWEEN_TABLES 可保持交换数据的完整性。如果交换操作中的任何任务失败,整个操作则会失败并回退。
示例
以下示例创建两个已分区表,然后在两者之间交换某些分区。
这两个表的定义相同,且具有不同 year
值的分区。交换 year
= 2008 和 year
= 2009 的分区。这两个表都至少有两行要交换。
-
创建
customer_info
表:=> CREATE TABLE customer_info ( customer_id INT NOT NULL, first_name VARCHAR(25), last_name VARCHAR(35), city VARCHAR(25), year INT NOT NULL) ORDER BY last_name PARTITION BY year;
-
向
customer_info
表中插入数据:INSERT INTO customer_info VALUES (1,'Joe','Smith','Denver',2008), (2,'Bob','Jones','Boston',2008), (3,'Silke','Muller','Frankfurt',2007), (4,'Simone','Bernard','Paris',2014), (5,'Vijay','Kumar','New Delhi',2010); OUTPUT -------- 5 (1 row) => COMMIT;
-
查看表数据:
=> SELECT * FROM customer_info ORDER BY year DESC; customer_id | first_name | last_name | city | year -------------+------------+-----------+-----------+------ 4 | Simone | Bernard | Paris | 2014 5 | Vijay | Kumar | New Delhi | 2010 2 | Bob | Jones | Boston | 2008 1 | Joe | Smith | Denver | 2008 3 | Silke | Muller | Frankfurt | 2007 (5 rows)
-
创建第二个表
member_info
,其具有与customer_info
相同的定义:=> CREATE TABLE member_info LIKE customer_info INCLUDING PROJECTIONS; CREATE TABLE
-
向
member_info
表中插入数据:=> INSERT INTO member_info VALUES (1,'Jane','Doe','Miami',2001), (2,'Mike','Brown','Chicago',2014), (3,'Patrick','OMalley','Dublin',2008), (4,'Ana','Lopez','Madrid',2009), (5,'Mike','Green','New York',2008); OUTPUT -------- 5 (1 row) => COMMIT; COMMIT
-
查看
member_info
表中的数据:=> SELECT * FROM member_info ORDER BY year DESC; customer_id | first_name | last_name | city | year -------------+------------+-----------+----------+------ 2 | Mike | Brown | Chicago | 2014 4 | Ana | Lopez | Madrid | 2009 5 | Mike | Green | New York | 2008 3 | Patrick | OMalley | Dublin | 2008 1 | Jane | Doe | Miami | 2001 (5 rows)
-
要交换分区,请运行 SWAP_PARTITIONS_BETWEEN_TABLES 函数:
=> SELECT SWAP_PARTITIONS_BETWEEN_TABLES('customer_info', 2008, 2009, 'member_info'); SWAP_PARTITIONS_BETWEEN_TABLES ---------------------------------------------------------------------------------------------- 1 partition values from table customer_info and 2 partition values from table member_info are swapped at epoch 1045. (1 row)
-
查询这两个表以确认它们交换了各自的 2008 年和 2009 年记录:
=> SELECT * FROM customer_info ORDER BY year DESC; customer_id | first_name | last_name | city | year -------------+------------+-----------+-----------+------ 4 | Simone | Bernard | Paris | 2014 5 | Vijay | Kumar | New Delhi | 2010 4 | Ana | Lopez | Madrid | 2009 3 | Patrick | OMalley | Dublin | 2008 5 | Mike | Green | New York | 2008 3 | Silke | Muller | Frankfurt | 2007 (6 rows)
=> SELECT * FROM member_info ORDER BY year DESC; customer_id | first_name | last_name | city | year -------------+------------+-----------+---------+------ 2 | Mike | Brown | Chicago | 2014 2 | Bob | Jones | Boston | 2008 1 | Joe | Smith | Denver | 2008 1 | Jane | Doe | Miami | 2001 (4 rows)
4 - 最小化分区
默认情况下,Vertica 最多支持 1024 个 ROS 容器来存储给定投影的分区(请参阅投影参数)。ROS 容器包含共享相同分区键或相同分区组键的数据。根据每个分区的数据量,一个分区或分区组可以跨多个 ROS 容器。
鉴于此限制,不建议按高度精细的数据(例如,按 TIMESTAMP 列)对表进行分区。这样做会生成非常多的分区。如果分区数量需要超过 1024 个 ROS 容器,Vertica 会发出 ROS 推回警告并拒绝加载更多表数据。大量 ROS 容器也会对 DML 操作(例如 DELETE
)产生负面影响,这需要 Vertica 打开所有 ROS 容器。
在实践中,您不太可能接近此最大值。为了获得最佳性能,Vertica 建议未分组分区的数量介于 10 到 20 之间,并且不超过 50。此范围通常适用于大多数业务需求。
5 - 查看分区存储数据
Vertica 提供了多种方式来查看表分区的组织和存储方式:
-
查询
PARTITIONS
系统表。 -
转储分区键。
查询 PARTITIONS 表
下面的表和投影定义按订单日期对 store_order
数据进行分区,并将同一年份的分区分组在一起:
=> CREATE TABLE public.store_orders
(order_no int, order_date timestamp NOT NULL, shipper varchar(20), ship_date date)
PARTITION BY ((order_date)::date) GROUP BY (date_trunc('year', (order_date)::date));
=> CREATE PROJECTION public.store_orders_super
AS SELECT order_no, order_date, shipper, ship_date FROM store_orders
ORDER BY order_no, order_date, shipper, ship_date UNSEGMENTED ALL NODES;
=> COPY store_orders FROM '/home/dbadmin/export_store_orders_data.txt';
在将数据加载到此表后,可以查询 PARTITIONS
表,以确定所有节点上有多少个 ROS 容器存储投影 store_orders_unseg
的已分组分区。每个节点有八个 ROS 容器,每个容器存储一个分区组的分区:
=> SELECT COUNT (partition_key) NumPartitions, ros_id, node_name FROM PARTITIONS
WHERE projection_name ilike 'store_orders%' GROUP BY ros_id, node_name ORDER BY node_name, NumPartitions;
NumPartitions | ros_id | node_name
---------------+-------------------+------------------
173 | 45035996274562779 | v_vmart_node0001
211 | 45035996274562791 | v_vmart_node0001
212 | 45035996274562783 | v_vmart_node0001
213 | 45035996274562787 | v_vmart_node0001
173 | 49539595901916471 | v_vmart_node0002
211 | 49539595901916483 | v_vmart_node0002
212 | 49539595901916475 | v_vmart_node0002
213 | 49539595901916479 | v_vmart_node0002
173 | 54043195529286985 | v_vmart_node0003
211 | 54043195529286997 | v_vmart_node0003
212 | 54043195529286989 | v_vmart_node0003
213 | 54043195529286993 | v_vmart_node0003
(12 rows)
转储分区键
Vertica 提供了多个函数,允许您在多个级别检查各个分区在群集上的存储方式:
-
DUMP_PARTITION_KEYS
转储系统中所有投影的分区键。 -
DUMP_TABLE_PARTITION_KEYS
转储指定表的所有投影的分区键。 -
DUMP_PROJECTION_PARTITION_KEYS
转储指定投影的分区键。
给定前面的表和投影,DUMP_PROJECTION_PARTITION_KEYS
显示每个节点上四个 ROS 容器的内容:
=> SELECT DUMP_PROJECTION_PARTITION_KEYS('store_orders_super');
...
Partition keys on node v_vmart_node0001
Projection 'store_orders_super'
Storage [ROS container]
No of partition keys: 173
Partition keys: 2017-01-02 2017-01-03 2017-01-04 2017-01-05 2017-01-06 2017-01-09 2017-01-10
2017-01-11 2017-01-12 2017-01-13 2017-01-16 2017-01-17 2017-01-18 2017-01-19 2017-01-20 2017-01-23
2017-01-24 2017-01-25 2017-01-26 2017-01-27 2017-02-01 2017-02-02 2017-02-03 2017-02-06 2017-02-07
2017-02-08 2017-02-09 2017-02-10 2017-02-13 2017-02-14 2017-02-15 2017-02-16 2017-02-17 2017-02-20
...
2017-09-01 2017-09-04 2017-09-05 2017-09-06 2017-09-07 2017-09-08 2017-09-11 2017-09-12 2017-09-13
2017-09-14 2017-09-15 2017-09-18 2017-09-19 2017-09-20 2017-09-21 2017-09-22 2017-09-25 2017-09-26 2017-09-27
Storage [ROS container]
No of partition keys: 212
Partition keys: 2016-01-01 2016-01-04 2016-01-05 2016-01-06 2016-01-07 2016-01-08 2016-01-11
2016-01-12 2016-01-13 2016-01-14 2016-01-15 2016-01-18 2016-01-19 2016-01-20 2016-01-21 2016-01-22
2016-01-25 2016-01-26 2016-01-27 2016-02-01 2016-02-02 2016-02-03 2016-02-04 2016-02-05 2016-02-08
2016-02-09 2016-02-10 2016-02-11 2016-02-12 2016-02-15 2016-02-16 2016-02-17 2016-02-18 2016-02-19
...
2016-11-01 2016-11-02 2016-11-03 2016-11-04 2016-11-07 2016-11-08 2016-11-09 2016-11-10 2016-11-11
2016-11-14 2016-11-15 2016-11-16 2016-11-17 2016-11-18 2016-11-21 2016-11-22 2016-11-23 2016-11-24 2016-11-25
Storage [ROS container]
No of partition keys: 213
Partition keys: 2015-01-01 2015-01-02 2015-01-05 2015-01-06 2015-01-07 2015-01-08 2015-01-09
2015-01-12 2015-01-13 2015-01-14 2015-01-15 2015-01-16 2015-01-19 2015-01-20 2015-01-21 2015-01-22
2015-01-23 2015-01-26 2015-01-27 2015-02-02 2015-02-03 2015-02-04 2015-02-05 2015-02-06 2015-02-09
2015-02-10 2015-02-11 2015-02-12 2015-02-13 2015-02-16 2015-02-17 2015-02-18 2015-02-19 2015-02-20
...
2015-11-02 2015-11-03 2015-11-04 2015-11-05 2015-11-06 2015-11-09 2015-11-10 2015-11-11 2015-11-12
2015-11-13 2015-11-16 2015-11-17 2015-11-18 2015-11-19 2015-11-20 2015-11-23 2015-11-24 2015-11-25
2015-11-26 2015-11-27
Storage [ROS container]
No of partition keys: 211
Partition keys: 2014-01-01 2014-01-02 2014-01-03 2014-01-06 2014-01-07 2014-01-08 2014-01-09
2014-01-10 2014-01-13 2014-01-14 2014-01-15 2014-01-16 2014-01-17 2014-01-20 2014-01-21 2014-01-22
2014-01-23 2014-01-24 2014-01-27 2014-02-03 2014-02-04 2014-02-05 2014-02-06 2014-02-07 2014-02-10
2014-02-11 2014-02-12 2014-02-13 2014-02-14 2014-02-17 2014-02-18 2014-02-19 2014-02-20 2014-02-21
...
2014-11-04 2014-11-05 2014-11-06 2014-11-07 2014-11-10 2014-11-11 2014-11-12 2014-11-13 2014-11-14
2014-11-17 2014-11-18 2014-11-19 2014-11-20 2014-11-21 2014-11-24 2014-11-25 2014-11-26 2014-11-27
Storage [ROS container]
No of partition keys: 173
...