微分区和数据聚类¶
传统数据仓库依靠对大型表进行静态分区来实现可接受的性能,并实现更好的扩展。在这些系统中,分区 是一个管理单元,使用专门的 DDL 和语法独立操纵。但静态分区有许多公认的局限性,如维护开销和数据扭曲,可能导致分区大小不成比例。
与数据仓库相比,Snowflake 数据平台实现了一种强大而独特的分区形式,称为 微分区,它具备静态分区的所有优点,杜绝了静态分区已知的局限性,还提供了额外的显著优势。
注意
混合表 基于一种架构,这种架构不支持标准 Snowflake 表中可用的某些功能(例如群集密钥)。
什么是微分区?¶
Snowflake 表中的所有数据都会自动划分到微分区中,微分区是连续的存储单元。每个微分区包含 50 MB 至 500 MB 的未压缩数据(注意,在 Snowflake 中的实际大小要小一些,因为数据在存储时始终经过压缩)。表中的行组映射到单个微分区,并以列式方式组织。这种大小和结构允许对超大型表(可能由数百万乃至数亿个微分区构成)进行高度精细的修剪。
Snowflake 会存储有关微分区中存储的所有行的元数据,包括:
微分区中各列的值范围。
非重复值的数量。
用于优化和高效查询处理的附加属性。
备注
系统会对所有 Snowflake 表自动执行微分区。在插入/加载数据时,将使用数据的排序透明地对表进行分区。
微分区的优势¶
Snowflake 的表数据分区方法有以下优势:
不同于传统的静态分区,Snowflake 的微分区是自动生成的,无需事先显式定义,也不需要用户进行维护。
顾名思义,微分区是非常小的(在压缩前为 50 到 500 MB),因此能实现极其高效的 DML 和细粒度修剪,从而加快查询速度。
微分区的值范围可以重叠,再加上其大小一贯较小,有助于防止数据扭曲。
列独立存储在微分区内,通常称为 列式存储。这支持有效扫描单个列;只需要扫描查询引用的列。
在微分区内,列也是单独压缩的。Snowflake 会自动为每个微分区中的列确定最有效的压缩算法。
通过为每个表指定一个群集密钥,可以在特定表上启用群集。有关指定群集密钥的信息,请参阅:
有关群集的其他信息,包括选择对哪些表进行群集的策略,请参阅:
微分区的影响¶
DML¶
所有 DML 操作(如 DELETE、 UPDATE、 MERGE)都利用了底层的微分区元数据,以方便和简化表元维护。例如,某些操作(如删除表中的所有行)是仅限元数据的操作。
删除表中的一列¶
删除表中的一列后,执行 drop 语句时不会对包含已删除列数据的微分区进行重写。删除的列中的数据仍在存储中。有关详细信息,请参阅 ALTER TABLE 使用说明。
查询修剪¶
Snowflake 维护的微分区元数据可在查询运行时精确修剪微分区中的列,包括含有半结构化数据的列。换言之,如果某查询指定了针对一个值范围的筛选谓词,以访问该范围内 10% 的值,那么理想情况下,该查询只扫描 10% 的微分区。
例如,假设一个大型表包含一年的历史数据,其中有日期和小时列。假设数据分布均匀,那么理想情况下,针对特定小时的查询应该扫描表中 1/8760 的微分区,然后仅扫描微分区中包含小时列数据的部分;Snowflake 使用分区的列式扫描,因此如果查询仅按一列进行筛选,则不会扫描整个分区。
换言之,扫描的微分区和列式数据的比例越接近于选定实际数据的比例,对表进行修剪的效率就越高。
对于时间序列数据,这种程度的修剪可使查询范围(即“切片”)细化到一小时甚至更短,从而实现亚秒级响应时间。
并非所有谓词表达式都能用于修剪。例如,即便子查询的结果是常量,Snowflake 也不会基于带有子查询的谓词修剪微分区。
什么是数据聚类?¶
通常情况下,表中存储的数据会按照自然维度(如日期和/或地理区域)进行排序/排列。这种“聚类”是查询的一个关键因素,因为未排序或仅部分排序的表数据可能会影响查询性能,对于超大型表尤其明显。
在 Snowflake 中,当数据插入/加载到表中时,系统会收集并记录在此过程中创建的每个微分区的聚类元数据。Snowflake 随后会利用这些聚类信息,避免在查询过程中对微分区进行不必要的扫描,从而显著加快引用这些列的查询的性能。
下图展示了 Snowflake 表 t1
,其中有四列按日期排序:
表由 24 行组成,分别存储在 4 个微分区中,所有行平均分配到各微分区之间。在每个微分区内,数据按列进行排序和存储,这使得 Snowflake 可对表的查询执行以下操作:
首先,修剪查询不需要的微分区。
随后在其余微分区内按列进行修剪。
请注意,此图仅用作 Snowflake 在微分区中使用的数据聚类的小比例概念表示。一个典型的 Snowflake 表可能包含数千乃至数百万个微分区。
为微分区维护的聚类信息¶
Snowflake 维护表中微分区的聚类元数据,其中包括:
构成表的微分区总数。
包含彼此重叠的值(指定的表列子集内)的微分区数量。
重叠的微分区的深度。
聚类深度¶
填充表的聚类深度用于衡量表中指定列的重叠微分区的平均深度(1
或更大)。平均深度越小,表与指定列相关的聚类就越好。
聚类深度可用于多种用途,包括:
监控大型表的聚类“健康状况”,尤其是在对表执行 DML 的过程中。
确定大型表能否受益于显式定义 群集密钥。
没有微分区的表(即未填充的表/空表)的聚类深度为 0
。
备注
表的聚类深度 并非 表聚类是否良好的绝对或精确衡量标准。归根结底,查询性能才是衡量表聚类程度的最佳指标:
如果对某个表的查询的执行效果符合需要或预期,则该表很可能聚类良好。
如果查询性能随着时间的推移而降低,则表很可能不再聚类良好,并且有可能从聚类中受益。
聚类深度示意图¶
在下图的概念示例中,表由五个微分区组成,这些微分区的值从 A 到 Z 不等,此示例展示了重叠如何影响聚类深度:
如此图所示:
最初,所有微分区的值范围是重叠的。
随着重叠微分区数量的减少,重叠深度也随之缩小。
在没有任何微分区的值范围存在重叠时,微分区被认为处于 *恒定状态*(即无法通过聚类加以改进)。
此图并不代表实际表。在实际表中,数据包含在大量微分区中,不可能为了提高查询性能而使所有微分区达到恒定状态,也不需要这样做。
监控表的聚类信息¶
为了查看/监控表的聚类元数据,Snowflake 提供了以下系统函数:
有关这些函数如何使用聚类元数据的更多详情,请参阅 聚类深度示意图 (本主题内容)。