跳到主要内容

recluster table

概述

聚类受到Snowflake中的数据聚类和Oracle中的属性聚类启发。

聚簇表根据表中某些列的值以有序的方式存储数据。聚类有利于分区消除和文件碎片整理。

默认情况下,数据按照自然维度存储在表中。我们需要根据聚类键对表进行重新聚类。另一方面,即使聚簇表已经很好地聚类,如果不断写入新数据,聚类效果会随着时间的推移而变差。因此,有必要添加重新聚类操作。

设计

有关更详细的原理和图片,请参阅snowflake auto clustering

对整个表进行排序的成本非常高,尤其是对于不断有新数据流入的表。为了在高效剪枝和低成本之间取得平衡,表只需要大致排序而不是完全排序。因此,在指标中引入了两个指标来确定表是否聚类良好。重新聚类的目标是减少overlapdepth

为了避免对同一块数据进行多次搅动,我们将块分成不同的层次,类似于LSM树。重新聚类类似于LSM的压缩操作。level表示该块中的数据被聚类的次数。重新聚类操作在同一层次上进行。

pub struct ClusterStatistics {
... ...
pub level: i32,
}

重新聚类操作的工作流程分为两个任务:块选择和块合并。

语法

alter table [if exists] tbl_name recluster [final] [where condition]

如果指定final,优化将一直进行,直到表聚类良好为止。否则,重新聚类工作流程只会运行一次。

该语句应由表上的DML触发。

指标

  • overlap 与给定块重叠的块数。

  • depth 在同一位置重叠的块数。这些点从聚类值域范围的最小值和最大值中收集。

块选择

新流入数据的初始层次为0。我们首先关注较新的数据,换句话说,选择操作优先在层次0上进行。这样做的好处是减少写放大。

  1. 计算每个点的深度和块的重叠,并汇总得到avg_depth。该算法已经在system$clustering_information中体现,这里不再重复。avg_depth的理想结果是1。为了实现大致排序,考虑定义一个阈值或比例(threshold = blocks_num * ratio)。只要avg_depth不大于这个阈值,该层次的块就可以被认为是聚类良好的,然后我们在下一层次进行块选择。

  2. 选择深度最高的点范围(一个或多个),并将该范围内的块作为下一阶段块合并的对象集。如果存在多个深度最高的范围,可能会有多组块可以在块合并期间并行化。

提示:

1. 表在有数据时可能会创建或更改聚类键,因此可能存在未按聚类键排序的块。考虑在重新聚类时暂时忽略这些块。

2. 如果一个块的聚类键只有一个值(最大值和最小值相等,达到常量状态)且其row_num为1_000_000,将其层次设置为-1并在重新聚类时过滤掉。

3. 选择的块可能需要考虑总大小,否则排序可能会导致内存不足。

块合并

对收集的块进行排序和合并。合并后的块超过一定阈值(1_000_000行)后,将分成多个块。新生成的块放入下一层次。

组织块并生成新的段和快照,最后更新表元数据。如果在此时有新的DML执行,当前工作流程将无法提交并返回错误。我们需要考虑具体的处理流程。

选择和合并操作重复进行,直到表聚类良好为止。

开始使用 Databend Cloud
低成本
快速分析
多种数据源
弹性扩展
注册