可以为新表和现有表指定分区:
-
使用 CREATE TABLE 为表定义分区。
-
通过使用 ALTER TABLE 修改定义,为现有表指定分区。
-
创建分区组以将分区合并为逻辑子集,从而最大限度减少 ROS 存储的使用。
可以为新表和现有表指定分区:
使用 CREATE TABLE 为表定义分区。
通过使用 ALTER TABLE 修改定义,为现有表指定分区。
创建分区组以将分区合并为逻辑子集,从而最大限度减少 ROS 存储的使用。
使用 CREATE TABLE 对新表进行分区,由 PARTITION BY 子句指定:
CREATE TABLE table-name... PARTITION BY partition‑expression [ GROUP BY group‑expression ] [ REORGANIZE ];
以下语句创建 store_orders
表并将数据加载到其中。CREATE TABLE 语句包含一个简单的分区子句,指定按年份对数据进行分区:
=> CREATE TABLE public.store_orders
(
order_no int,
order_date timestamp NOT NULL,
shipper varchar(20),
ship_date date
)
UNSEGMENTED ALL NODES
PARTITION BY YEAR(order_date);
CREATE TABLE
=> COPY store_orders FROM '/home/dbadmin/export_store_orders_data.txt';
41834
当 COPY 将新表数据加载到 ROS 存储中时,Tuple Mover 会将每年的订单划分为单独的分区,且将这些分区合并到 ROS 容器中,以执行表的分区子句。
在这种情况下,Tuple Mover 为加载的数据创建四个分区键(2017、2016、2015 和 2014),并将数据相应划分到单独的 ROS 容器中:
=> SELECT dump_table_partition_keys('store_orders');
... Partition keys on node v_vmart_node0001
Projection 'store_orders_super'
Storage [ROS container]
No of partition keys: 1
Partition keys: 2017
Storage [ROS container]
No of partition keys: 1
Partition keys: 2016
Storage [ROS container]
No of partition keys: 1
Partition keys: 2015
Storage [ROS container]
No of partition keys: 1
Partition keys: 2014
Partition keys on node v_vmart_node0002
Projection 'store_orders_super'
Storage [ROS container]
No of partition keys: 1
Partition keys: 2017
...
(1 row)
当新数据加载到 store_orders
中时,Tuple Mover 会将其合并到适当的分区中,以此根据需要创建新的分区键。
使用 ALTER TABLE 对现有表进行分区或重新分区,由 PARTITION BY
子句指定:
ALTER TABLE table-name PARTITION BY partition‑expression [ GROUP BY group‑expression ] [ REORGANIZE ];
例如,可以对前面定义的 store_orders
表进行重新分区。下面的 ALTER TABLE 将每年的所有 store_orders
数据划分为每月分区,每个分区键标识订单日期的年份和月份:
=> ALTER TABLE store_orders
PARTITION BY EXTRACT(YEAR FROM order_date)*100 + EXTRACT(MONTH FROM order_date)
GROUP BY EXTRACT(YEAR from order_date)*100 + EXTRACT(MONTH FROM order_date);
NOTICE 8364: The new partitioning scheme will produce partitions in 42 physical storage containers per projection
WARNING 6100: Using PARTITION expression that returns a Numeric value
HINT: This PARTITION expression may cause too many data partitions. Use of an expression that returns a more accurate value, such as a regular VARCHAR or INT, is encouraged
WARNING 4493: Queries using table "store_orders" may not perform optimally since the data may not be repartitioned in accordance with the new partition expression
HINT: Use "ALTER TABLE public.store_orders REORGANIZE;" to repartition the data
执行此语句后,Vertica 会删除现有的分区键。但是,partition 子句会省略 REORGANIZE,以便现有数据仍然根据前一个 partition 子句进行存储。这可能会使表分区处于不一致状态,并对查询性能、DROP_PARTITIONS 和节点恢复产生负面影响。在这种情况下,必须通过以下方式之一显式请求 Vertica 将现有数据重新组织到新分区中:
发出 ALTER TABLE...REORGANIZE:
ALTER TABLE table-name REORGANIZE;
调用 Vertica 元函数 PARTITION_TABLE。
例如:
=> ALTER TABLE store_orders REORGANIZE;
NOTICE 4785: Started background repartition table task
ALTER TABLE
ALTER TABLE...REORGANIZE 和 PARTITION_TABLE 的运行方式相同:两者都会拆分分区键与新 partition 子句不相符的任何 ROS 容器。在执行下一次合并时,Tuple Mover 会将分区合并到相应的 ROS 容器中。
分区组将分区合并为逻辑子集,从而最大限度减少 ROS 存储的使用。减少存储分区数据的 ROS 容器数有助于促进 DELETE
和 UPDATE
等 DML 操作,并避免 ROS 推回。例如,可以按年份对日期分区进行分组。通过这样做,Tuple Mover 会为每个年份组分配 ROS 容器,并相应地将各个分区合并到这些 ROS 容器中。
可以通过使用 GROUP BY
子句限定 PARTITION BY
子句来创建分区组:
ALTER TABLE table-name PARTITION BY partition‑expression [ GROUP BY group‑expression ]
GROUP BY
子句指定如何将分区键合并到组中,其中每个组由唯一的分区组键标识。例如,以下
ALTER TABLE
语句指定按订单日期对 store_orders
表进行重新分区(如对新表进行分区中所示),按年份对分区键进行分组。组表达式 DATE_TRUNC('year', (order_date)::DATE)
使用分区表达式 order_date::DATE 生成分区组键:
=> ALTER TABLE store_orders
PARTITION BY order_date::DATE GROUP BY DATE_TRUNC('year', (order_date)::DATE) REORGANIZE;
NOTICE 8364: The new partitioning scheme will produce partitions in 4 physical storage containers per projection
NOTICE 4785: Started background repartition table task
在这种情况下,order_date
列的日期跨越四年。Tuple Mover 会创建四个分区组键,并相应地将 store_orders
分区合并到组特定的 ROS 存储容器中:
=> SELECT DUMP_TABLE_PARTITION_KEYS('store_orders');
...
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-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-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-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-11-25 2014-11-26 2014-11-27
Projection 'store_orders_super'
Storage [ROS container]
No of partition keys: 173
...
此示例演示了分区分组如何促进更有效地使用 ROS 存储。但是,将所有分区分组到多个大型静态 ROS 容器中可能会对性能产生负面影响,特别是对于频繁执行 DML 操作的表。特别是,频繁的加载操作可能会产生相当大的合并开销,进而降低性能。
Vertica 建议使用
CALENDAR_HIERARCHY_DAY
作为 partition 子句的组表达式。此函数自动将 DATE
分区键分组为年、月和日的动态层次结构。这样做有助于最大限度地减少与合并相关的问题。有关详细信息,请参阅分层分区。
可以使用各种分区管理函数(例如
DROP_PARTITIONS
或
MOVE_PARTITIONS_TO_TABLE
),来定位给定分区组内或跨多个分区组的订单日期范围。在前面的示例中,每个组都包含给定年份内不同日期的分区键。可以使用 DROP_PARTITIONS
删除跨越两年(2014 年和 2015 年)的订单日期:
=> SELECT DROP_PARTITIONS('store_orders', '2014-05-30', '2015-01-15', 'true');