当前位置: 首页 > 工具软件 > Vertica > 使用案例 >

Vertica分区

裘光启
2023-12-01

本文翻译整理自:https://www.vertica.com/kb/Vertica-Partitions-The-FAQs/Content/FAQs/Vertica-Partitions-The-FAQs.htm

基础知识

vertica的分区方法与目的与其他数据库没有区别,都是为了更高效的对数据进行管理。

vertica中有一个活动分区的概念,特指最新创建的那个分区。非活动分区包含可能不需要经常访问的数据。在执行合并时,对于非活动分区,Tuple Mover将所有ROS容器组合到一个ROS容器中。在活动分区中,Tuple Mover使用基于分层的算法来组合ROS容器。

可以通过更改ActivePartitionCount配置参数来更改每个表的活动分区数,默认值为1。
如果经常将数据加载到最后两个分区,请将ActivePartitionCount更改为2。这是一个全局配置参数,会影响每个表。如果将其设置为2,则Tuple Mover将分层算法应用于最后两个创建的分区。
增加ActivePartitionCount可减少Tuple Mover操作的数量。但是,您的投影中可能会有太多的ROS容器。

Vertica建议您仅分区大型事实表,不要对小表或维度表进行分区,这样做会创建大量的ROS容器,这会快速增加目录大小并影响查询性能。

为表定义分区表达式时,请考虑以下事项:

  • 数据保留政策
  • 经常使用的查询谓词
  • 分区粒度可能对每个节点的每个投影的ROS容器数量和每个节点的ROS文件总数产生的影响

分区和存储修剪

分区如何影响数据生命周期管理?

在Vertica数据库中对大型事实表进行分区可以简化数据生命周期管理并提高查询性能。

Vertica提供以下功能:

  • 从表中删除分区。(DROP_PARTITION函数)
  • 将很少使用的分区移动到存档表。(MOVE_PARTITIONS_TO_TABLE函数)
  • 将很少使用的分区移动到较便宜的存储。
  • 从存档还原分区。

vertica的一些分区函数可以参考:
https://www.vertica.com/docs/9.2.x/HTML/Content/Authoring/SQLReferenceManual/Functions/VerticaFunctions/PartitionManagement/PartitionManagementFunctions.htm?tocpath=SQL Reference Manual|SQL Functions|Vertica Meta-Functions|Partition Management Functions|_____0
vertica的存储策略可以参考:
https://www.vertica.com/docs/9.2.x/HTML/Content/Authoring/AdministratorsGuide/StorageLocations/CreatingStoragePolicies.htm

什么是存储修剪以及它与分区有什么关系?

分区数据被分隔到各个存储容器中。因此,在分区列上使用谓词的查询可以从Vertica存储修剪功能中获益。
在查询规划阶段,数据库优化器会识别不包含该查询所需数据的存储容器。在查询处理期间,Vertica执行引擎省略了不存储适用值的存储容器,从而减少了I / O并提高了查询性能。

如何判断我的查询是否利用了分区和存储修剪?

1.配置查询以获取transaction_id和statement_id

PROFILE SELECT * FROM <table_name> WHERE <column_name> BETWEEN 5 AND 7;
NOTICE 4788:  Statement is being profiled
HINT:  Select * from v_monitor.execution_engine_profiles where 
transaction_id=54043195528458555 and statement_id=1;
NOTICE 3557:  Initiator memory for query: [on pool general: 19543 KB, minimum: 19543 KB]
NOTICE 5077:  Total memory required by query: [19543 KB]

2.检查QUERY_EVENTS系统表中的该事务,并确定查询计划指示在执行该查询时从处理中消除分区的位置:

=> SELECT node_name , event_details FROM query_events WHERE 
   event_type = 'PARTITIONS_ELIMINATED' AND transaction_id = 54043195528458555
   AND statement_id=1;
    node_name     |                       event_details
------------------+-----------------------------------------------------------
v_vmart_node0003  | Using only 1 stores out of 3 for projection public.tab_b0
v_vmart_node0002  | Using only 1 stores out of 5 for projection public.tab_b0
v_vmart_node0001  | Using only 1 stores out of 2 for projection public.tab_b0
(3 rows)

分区和ROS文件以及ROS容器

ROS文件和ROS容器有什么区别?

当用户使用DIRECT发出COPY语句时,Vertica会为每列创建一个ROS文件。ROS容器是ROS文件的逻辑分组。由于COPY DIRECT或Tuple Mover操作,Vertica创建了ROS容器。

为什么我要考虑每个节点每个投影的ROS容器数量?

Vertica将分区数据隔离到不同的存储容器中。由于Vertica不会跨分区合并数据,因此拥有太多小分区可能会使存储容器的数量接近最大ROS容器数:1024。

如果达到特定投影的此限制,并尝试将新数据加载到该投影中,则加载会因“太多ROS容器”错误而失败。如果您有此错误,请执行以下操作之一:

  • 使用ALTER_PARTITION将分区表达式更改为更精细的分区方案。
  • 使用MOVE_PARTITION将旧分区移动到存档表。
每个节点的ROS容器总数如何影响我的数据库?

每个节点的ROS文件数量为:

(storage containers)x(每个投影的列数)

ROS文件的数量可能是catalog目录大小的主要贡献者。拥有大catalog目录会占用系统内存并降低其他数据库操作的速度,例如系统表查询,数据库启动,数据库备份和临时恢复。

如果每个节点都有一个包含100万个ROS文件的目录,则目录大小约为3-4GB。如果在你进行控制之前ROS文件的数量一直在增加,则可能不会释放catalog目录内存。在Vertica重新获取已释放的catalog目录内存后,内存可供将来使用。但是,在重启该节点之前,节点实际上不会释放该内存。

两个例子
大的catalog目录

你有一个数据库

  • 1,000个 table
  • 每个table 2个投影
  • 每个table 50列(平均)
  • 每个节点50个ROS容器

所以,每个节点大约有500万个ROS文件。

(1000表)x(每个表2个投影)= 2000个投影
(50列)x(2000个投影)= 10,0000 x(每个投影50个ROS)= 5,000,000个ROS文件

您可以按日期对300个表进行分区,并将数据保留一年。这样做可以使用Vertica分区管理功能管理单个日期的数据。然而,这使得ROS数量增加了大约1000万,使目录的大小翻了一番:

(300个表)x(2个投影)= 600个投影
(365天)x 600 = 219,000 x(50列)= 10,900,000个ROS文件

在这种情况下,您有两种选择:

  • 按天分区每个节点每个投影至少添加365个ROS容器,因此您只需要对少量表按天分区。避免对小表进行分区,如果可能,请对大多数表按周或按月进行分区。
  • 如果需要按天进行分区,请通过将类似的表组合到单个表中来确定可以减少ROS容器数量的位置。schema通常继承自传统OLTP系统,后者根据地理位置将表拆分为多个表,以提高查询性能。为获得最佳结果,请将这些表组合到一个表中。
每个投影的ROS容器太多

你有一个数据库:

  • 100个 table
  • 每个table 2个投影
  • 每个table 50列
  • 每个节点50个ROS容器

所以,您有200个投影和500,000个ROS文件:

(100个表)x(每个表2个投影)= 200个投影
(50列平均值)x(200个投影)=  10,000 x(每个节点50个ROS容器)=  500,000个ROS文件

假设您希望按天对10个表进行分区,并将数据保留三年。这样做允许您使用分区管理功能管理每天的数据。在这种情况下,您可能不会累积大量的ROS文件。但是,在达到第三年加载数据时,你会遇到ROS pushback(1024个ROS容器)。

1个表x(365 x 3)= 1095个ROS容器用于非活动分区 

结果,在活动分区中没有剩余空间来接收数据。

或者,如果按周划分:

1个表x(52 x 3)= 156个ROS容器用于非活动分区 

这种替代方案可以显著减少ROS容器。在这种情况下,请考虑按周而不是按天对数据进行分区。

在规划未来数据增长时,请考虑这些问题。

补充:对于vertica,还有一种方法去解决上述问题。就是采用分层分区,分层分区是一种可以灵活进行分区的方式。比如说,可以针对近一个月的数据按天分区,大于一个月到一年的数据按月分区,大于一年的数据按照年进行分区。这样既可以减少分区的数量,又可以确保近期使用的数据有更细化的分区。
关于分层分区,可参考:https://www.vertica.com/docs/9.2.x/HTML/Content/Authoring/AdministratorsGuide/Partitions/HierarchicalPartitioning.htm?tocpath=Administrator's Guide|Partitioning Tables|_____2
以及
https://www.vertica.com/blog/hierarchical-partitioning/

重新分区及重新组织

您可以使用以下内容对现有表进行分区或更改表的分区表达式:

=> ALTER TABLE < table_name > PARTITION BY < partition_expression >

运行此语句时,将立即擦除存储容器的任何现有分区键信息。您必须使用REORGANIZE关键字根据新的分区表达式重建此信息。
注意:节点关闭时,请勿更改表分区。

使用REORGANIZE关键字时会发生什么?

分别或一起使用PARTITION BY和REORGANIZE关键字对表进行分区或重新分区,如下所示:

=> ALTER TABLE <table_name> PARTITION BY <partition_expression> REORGANIZE;

运行此语句时,Vertica会删除所有现有分区键,重新分区表并重新组织表。

REORGANIZE操作是在后台运行的Tuple Mover操作的变体。重组操作以块的形式读取数据,以免影响数据库性能。然后,REORGANIZE根据新的分区方案将数据写入ROS容器,并将分区键添加到ROS容器对象。

可以推迟REORGANIZE吗?这种延迟有什么影响?

为了最小化正在运行的数据库的性能,REORGANIZE一次只能处理一部分ROS容器。

重新分区后延迟REORGANIZE操作会导致以下限制:

  • 您无法在分区表达式已更改但未REORGANIZE的表上运行分区函数。
  • 对于分区表,没有分区键的ROS容器不参与Tuper Mover合并。这可能导致ROS的pushback。

重新分区后尽快REORGANIZE。监视REORGANIZE操作的进度,直到完成更改表上的所有投影。

如何监控REORGANIZE流程的状态?

使用以下系统表监视重组后台进度:

VS_TUPLE_MOVER_OPERATIONS
PARTITION_STATUS
PARTITION_REORGANIZE_ERRORS

要查看给定表的分区历史记录,请查询系统表CATALOG_EVENTS。

如何删除表分区?

要更改表以使其不再分区,请使用以下语句:

=> ALTER TABLE <table_name> REMOVE PARTITIONING;

从表中删除分区后,Vertica会像处理任何其他非分区表一样处理该表。Vertica使用分层算法合并ROS容器。

分区限制注意事项

每个表的分区数量是否有限制?

每个表的分区数没有限制。但是,分区的数据被分隔为ROS容器。Vertica将每个节点的每个投影的ROS容器数限制为1024,因此每个表的限制基本上是1024个分区。

Vertica可防止单个COPY DIRECT语句加载超过1024个分区。

如果您有超过365个分区(约为限制的三分之一),请按投影计数观察ROS容器并监视Tuple Mover合并操作。如果有超过365个分区,则可能需要重新考虑该表的分区方案,或将未查询的分区移动到归档表。

如何确定内存中数据库目录的大小?

以下查询返回数据库目录的大小:

=> SELECT node_name,MAX(ts)AS ts,MAX(catalog_size_in_MB)
   AS catlog_size_in_MB 
   FROM 
   (SELECT node_name,
    TRUNC((dc_allocation_pool_statistics_by_second。“time”):: TIMESTAMP,
    'SS':: VARCHAR(2))AS ts,
    SUM ((dc_allocation_pool_statistics_by_second.total_memory_max_value 
    -  dc_allocation_pool_statistics_by_second.free_memory_min_value))/(1024 * 1024)
    AS catalog_size_in_MB from dc_allocation_pool_statistics_by_second GROUP BY 1,
    TRUNC((dc_allocation_pool_statistics_by_second。“time”):: TIMESTAMP,
    'SS':: VARCHAR(2))
    )
    subquery_1 GROUP BY 1 ORDER BY 1 LIMIT 50;
如何检查分区是否有助于大型目录?

有几种情况可能导致大型数据库目录。大型目录是10 GB或更大的目录。

以下查询返回具有最大ROS容器的前50个投影。如果您看到结果中的表已分区且分区计数很高,请考虑修改分区方案,以便Vertica创建更少的分区。

=> SELECT s.node_name,p.table_schema,s.projection_name,
   COUNT(DISTINCT s.storage_oid)storage_container_count,
   COUNT(DISTINCT partition_key)partition_count,
   COUNT(r.rosid)ros_file_count 
   FROM storage_containers s LEFT OUTER JOIN PARTITIONS p 
   ON s.storage_oid = p.ros_id JOIN vs_ros r 
   ON r.delid = s.storage_oid 
   GROUP BY 1,2,3 ORDER BY 4 DESC LIMIT 50;

关于分区,更多内容可参考:https://www.vertica.com/docs/9.2.x/HTML/Content/Authoring/AdministratorsGuide/Partitions/PartitioningTables.htm

 类似资料: