使用 Snowflake 进行数据建模——掌握 Snowflake 的架构

346 阅读21分钟

自数据库诞生以来,它们就不断面临在日益增长的数据量和处理需求下管理并发性和可扩展性的挑战。多年来,许多创新设计被尝试过,并取得了不同程度的成功。然而,这些成功往往伴随着新的缺点。

Snowflake 团队认识到,要解决数据存储和分析之间独立消费需求的传统难题,需要一种全新的方法。团队决定设计一个能够原生运行在云计算平台之上的数据库,从而提供几乎无限的可扩展性。最终,他们的努力促成了 Snowflake 所称的 Data Cloud(数据云) 的诞生——一个通过存储与计算分离实现实时数据共享和按需工作负载扩展的平台。


本章将涵盖以下内容:

  • 探讨过去数据库在实现可扩展性方面的尝试
  • 了解 Snowflake 如何构建原生云端运行的可扩展数据库
  • 发现 Snowflake 创新架构所实现的独特功能
  • 理解 Snowflake 可变支出模式的成本结构
  • 学习如何利用各种缓存形式节省成本并提升性能

为了真正理解 Snowflake 的成就,我们需要回顾其前身所采用的传统架构及其试图解决的局限性。


传统架构

要充分理解 Snowflake 数据云的创新,我们必须回顾其前身的设计及相关局限性。在云出现之前,数据库主要以物理的本地设备形式存在,自诞生以来就面临同样的挑战:可扩展性。

过去,数据库依赖于物理服务器来提供存储和处理能力。随着使用量的增加,内存会被填满,CPU 需求也会达到可用极限,迫使用户增加服务器资源或完全更换服务器。这些应对措施都涉及维护和停机时间,因此硬件采购必须具有前瞻性,预测数据库未来几年的增长需求。

下图概述了传统数据库的结构及其关键组件。尽管处理能力、内存和磁盘空间可以在一定程度上定制,但它们都封装在一台无法扩展的物理机器中。

image.png

在云架构解锁软件即服务(SaaS) 模式并引入可变支出定价之前,硬件采购需要大量的资本支出(CapEx)。因此,硬件规模的规划——估算当前和未来的计算需求——需要谨慎的计划。保守估计可能导致比预期更早地升级,而高估则意味着为尖端技术支付高昂费用,但多年内未能充分利用其潜力。

尽管数据量和 CPU 需求通常会随着业务的增长同步增长,但存储或计算的意外使用高峰也很常见,这会引发类似的麻烦。正是在这个背景下,共享磁盘(shared-disk)和共享无(shared-nothing)等新架构出现,以解决物理机器扩展的限制。

首先,让我们了解共享磁盘架构相较于传统设计引入了哪些变化以及它所提供的优势。


共享磁盘架构

共享磁盘方法使用一个中央存储位置,使其可供网络中的各种计算集群访问。这是一种简单的设计,但在同时锁定和访问数据时,由于物理实现的限制,容易出现问题。

下图展示了共享磁盘架构如何将数据存储从单个机器中外部化,并使其可供网络中的所有计算集群访问:

image.png

共享磁盘设计使得可以添加不同大小的计算集群,以满足组织内不同工作负载的需求。然而,这种设计不可避免地导致了瓶颈问题。在共享磁盘架构中,随着网络中集群数量的增加,对中央磁盘的争用也会愈发严重。这种设计未能兑现可扩展性的承诺,因为它在数据库中最重要的资源——数据上出现了瓶颈。

在共享磁盘架构失败的地方,共享无(shared-nothing) 架构几乎实现了成功。


共享无架构

像 AWS Redshift 和 Greenplum 等使用的共享无架构,通过将存储隔离并使其成为计算集群的一部分,避免了共享磁盘的相关问题。这种设计还解决了组织内不同团队的不同消费需求,使数据库集群能够根据需求调整规模。然而,正如我们在小学时学到的一样,“什么都不共享”并不是协作的最佳策略。

下图展示了共享无架构如何实现自给自足但相互隔离的数据库集群:

image.png

在共享无架构中创建数据库集群,特别是在虚拟云资源上运行的架构中,可以解决前期投资物理硬件的问题。然而,共享无架构中的节点需要通过数据传输来共享信息,这会降低性能。

将磁盘绑定到整体集群还意味着需要在存储和处理模式之间找到合适的平衡,而这些模式可能是相互独立的。例如,一个复杂的数据科学工作负载可能需要针对相对较小的数据集进行大量计算,而一个 ETL 批量加载过程可能需要相反的资源分配。然而,共享无平台并未提供太多选项来分别调整每种资源,也不容易维护和管理。

虽然共享无架构未能完全实现无缝且易于管理的可扩展性承诺,但它为像 Snowflake 这样的平台铺平了道路,使其通过云原生设计解决云计算的挑战。


Snowflake 的解决方案

为了解决自数据库诞生以来一直存在的可扩展性问题,Snowflake 团队制定了一种新方法,不受过去设计局限的束缚。他们开发了一个专为云环境原生构建的现代平台,利用云的独特功能实现并发性、可扩展性和实时协作。

Snowflake 的创新云架构仍然依赖于物理磁盘,但通过逻辑集成,使集中式存储可供其计算集群访问,同时避免并发瓶颈和数据复制的开销。最终,Snowflake 实现了共享磁盘和共享无架构所承诺的优点:将数据与计算工作负载分离,使其可以独立配置和调整大小。

Snowflake 完全运行在来自云平台(如亚马逊、微软和谷歌云)的虚拟资源上。Snowflake 以透明的方式处理与云提供商的所有交互,抽象底层虚拟资源,让客户通过统一的三层架构管理数据。


Snowflake 的三层架构

Snowflake 的架构由三层组成:存储、计算和云服务。Snowflake 管理这三层,使用户与底层云架构的交互变得透明。

以下图示说明了 Snowflake 的架构如何运行在云数据平台之上,同时将磁盘与虚拟计算集群分离,并管理一个单独的操作服务层(让用户无需担心这些细节):

image.png

现在,让我们逐一了解这三层架构,并解释它们如何结合在一起,从而实现 Snowflake 的创新功能,例如零复制克隆(Zero-Copy Cloning)时间旅行(Time Travel)


存储层

存储层负责将数据物理存储在托管 Snowflake 账户的云提供商的磁盘上。当数据加载到 Snowflake 中时,它会被压缩、加密,并逻辑上组织成表、模式和数据库。用户定义数据库及其对象的逻辑层次结构,而 Snowflake 则负责底层的分区和存储。用户只需为存储的数据付费,无需配置或调整存储大小。

后续章节将更详细地探讨 Snowflake 如何管理和优化数据存储,以及它提供的备份和冗余选项。现在,让我们了解 Snowflake 中的计算和虚拟仓库集群的工作方式。


计算层

计算层,也称为处理层或虚拟仓库层,提供了一组虚拟配置的 CPU 和临时内存资源,用于执行查询。这些集群被称为仓库(warehouses) ,可以按“T恤尺寸”进行配置——从 XS6XL 不等。Snowflake 通过这些仓库,以简单的公式简化了虚拟云资源的使用:仓库规模每增加一级,集群中虚拟服务器的数量翻倍,成本也相应翻倍。

将虚拟计算集群分组为仓库,并以简单的“T恤尺寸”表示,抽象了底层云架构,并确保无论 Snowflake 账户托管在哪个平台上,其使用方式都简单且一致。这种方式使仓库的扩展变得易于跟踪。“向上扩展”指将仓库调整到下一个更大的“T恤尺寸”,这会使集群中的服务器数量翻倍;而“向外扩展”则是向计算集群添加相同大小的仓库,以提高并发性(可以将向上扩展和向外扩展分别类比为计算能力的“乘以二”和“加一”)。


服务层

服务层在这种混合层模型中协调所有账户活动,管理从安全性到加密和元数据的一切。服务层处理诸如查询解析和优化、数据共享和缓存等操作。从用户登录开始,服务层在用户进行的每项仓库操作中都发挥作用。这一层提供的大量节省时间的工作和自动化正是 Snowflake 所宣传的亮点:为用户提供接近“零维护”、低成本和卓越性能的体验。


现在,让我们看看 Snowflake 的三层架构如何结合在一起,为用户解锁前所未有的可能性。

Snowflake 的功能

凭借其革命性的云架构,Snowflake 不断创新,为用户带来超越其初创时已让人惊艳的功能的性能提升。以下列出了一些与数据建模相关的最令人兴奋和实用的功能,尽管并非详尽无遗:


零复制克隆(Zero-Copy Cloning)

零复制克隆允许 Snowflake 用户在不物理复制数据的情况下克隆数据。由于无需移动数据,克隆可以瞬间完成,无论是克隆表还是整个数据库。克隆对象是其源对象的虚拟副本,因此不占用存储成本。一旦克隆或其源中的数据发生变化,克隆对象将变为物理对象,并开始消耗存储资源。

克隆是创建系统备份和测试环境的理想方式,可以在几秒内完成过去需要数天的工作。在对象级别,克隆是将数据跨环境迁移用于开发或调试的便捷方法。

另一项通过创新的列式存储技术(将在后续章节中详细解释)实现的增强功能是时间旅行(Time Travel)


时间旅行(Time Travel)

想象一下,能够回到过去的某个时刻,例如在你错误地删除生产环境中的表(以为是在测试环境中)之前。Snowflake 的时间旅行功能让这种场景成为可能。

通过时间旅行,用户可以查询或克隆来自过去某一时刻的数据,帮助从错误中恢复,或比较当前状态与过去的变化。时间旅行是 Snowflake 对象的内置备份功能,因此相较于未启用该功能的对象,它会消耗额外的存储,并带来相应的存储成本。后续章节将讨论如何配置时间旅行以平衡成本与灵活性。

现在,让我们从表备份转向 Snowflake 的最新创新之一:Hybrid Unistore 表


Hybrid Unistore 表

数据仓库通过联机分析处理(OLAP)架构高效执行大规模聚合和计算,满足分析工作负载的需求。然而,依赖单行操作或索引的用例在联机事务处理(OLTP)数据库中表现更好。在 2022 年 Snowflake 峰会上,一种新型表格被宣布,旨在为用户提供两者的最佳结合:Hybrid Unistore

Hybrid Unistore 表本质上是两种表格合二为一——分析表和事务表在后台协作,为用户提供统一的解决方案,同时实现两者的优势。与所有 Snowflake 对象一样,Hybrid 表通过服务层自动将工作负载路由到最适合任务的底层表,兑现了接近零维护的承诺。

后续章节将深入探讨 Hybrid Unistore 表,现在让我们从结构化数据的讨论转向 Snowflake 的另一个强项:处理非结构化数据


超越结构化数据

Snowflake 以其在关系表中的标杆性能和处理半结构化数据的灵活性而闻名。甚至非结构化文件也可以通过外部表支持。用户可以以一种熟悉且高效的方式,从单一平台处理任何格式的文件,像查询表一样简单。

半结构化文件(如 JSON 或类似格式的日志和层次结构)可以被加载到 Snowflake 中,并几乎不影响性能地像常规表一样查询。Snowflake 提供了广泛的函数库,允许用户处理半结构化记录或将其扁平化为结构化列。相关技术将在后续章节中详细讨论。

Snowflake 还支持非结构化数据,并可以通过外部表查询其元数据。外部表是基于外部阶段创建的元数据对象,它们是只读的,但支持关系建模的约束。有关使用外部表的更多信息,请参考 Snowflake 文档


性价比与成本管理

听起来所有这些功能和云的敏捷性似乎会非常昂贵,对吧?事实上,Snowflake 无需前期成本,提供具有竞争力的定价,并允许用户根据需求调整仓库规模,甚至完全暂停,从而往往比传统的本地硬件花费更少。

但需要注意的是,为了实现这一点,用户必须了解 Snowflake 的定价机制并有效管理它。

需要考虑的成本

与前期购买并在生命周期内使用的本地数据库不同,Snowflake 采用一种基于使用量的消费模型,称为可变支出模式(通常称为按需付费)。可变支出模式允许团队快速进行原型开发或概念验证实验,而无需前期投资,并通过监控和调整使用模式来控制成本。以下将详细解析使用 Snowflake 平台涉及的成本类型,以便在后续设计中做出明智的决策。

让我们从云中存储数据的成本开始。


存储成本

Snowflake 根据平台中存储数据的每日平均量向客户计费。由于 Snowflake 的服务层会自动压缩数据以优化存储,客户无需牺牲性能即可享受较低的存储成本。然而,不仅仅是原始数据会计入存储配额,时间旅行故障保护备份(将在下一章详细讨论)也需要考虑在内。

现在,让我们讨论处理数据的成本。


计算成本

Snowflake 的消费根据使用的虚拟仓库数量、运行时间及其规模计费。活跃的仓库以每秒计费(最低计费时间为 60 秒)。为了简化仓库定价的计算,Snowflake 使用了称为信用(credits) 的标准单位。

信用的具体成本取决于多个因素,例如云提供商、托管区域和 Snowflake 的版本(即 Standard、Enterprise、Business Critical 或 VPS)。一旦这些变量确定,一个信用等于一个 XS 仓库运行一小时

需要注意的重要一点是,只要仓库处于活跃状态,无论是否在运行查询,它都会消耗信用。因此,有效的成本策略应考虑何时实例化和关闭仓库(Snowflake 提供自动恢复和自动暂停选项),以及给定工作负载所需的仓库规模。

最后,我们来看运行和管理平台的成本。


服务成本

服务层管理诸如访问控制和查询优化等关键操作,还执行自动的无服务器任务,例如自动(重新)集群、加载流数据(Snowpipe)和复制操作。许多用户生成的操作(例如查询表元数据,如 countsummax,以及通过 showdescribe 命令检索对象元数据)由服务层处理,而无需活跃仓库的参与。

只要服务层的消耗不超过每日仓库消耗的 10%,其成本包含在仓库的信用中。当服务层消耗超过仓库支出的 10% 时,其操作按标准信用费率计费(即 XS 仓库运行一小时等于一信用)。


如何降低成本

在介绍了与 Snowflake 三层架构相关的成本后,接下来将讨论如何通过利用 Snowflake 的各种缓存机制来节省这些成本。

通过缓存节省成本

在本地数据库中,低效的操作会导致更长的执行时间。而在 Snowflake 的可变支出模式中,额外的执行时间还会带来金钱上的惩罚。因此,除了编写高效的 SQL 外,Snowflake 用户还应了解与服务层和虚拟计算层相关的各种缓存机制,借助预先计算的结果来提高效率。深入理解 Snowflake 的缓存机制还能为数据建模和构建数据管道提供重要参考。

让我们从服务层开始,熟悉它管理和提供的缓存类型。


服务层缓存

服务层处理两种类型的缓存:元数据缓存查询结果缓存

元数据缓存

服务层管理对象的元数据,例如结构、行数和每列的不同值。通过相关 SQL 函数或 Snowflake UI 查看这些元数据无需运行仓库,也不会消耗信用。

Snowflake 在表级别存储元数据(如字节大小和创建日期),并为表中每个微分区(micro-partition) 的列维护统计信息(如行数、最小/最大值和空值计数)。

微分区(MICRO-PARTITIONS)

微分区是表中按列组织的一组行。微分区允许对包含数百万微分区的大表进行细粒度剪枝。Snowflake 服务层会在表中执行 DML 操作时自动创建和管理微分区。有关详细信息,请参阅 Snowflake 文档中的 微分区与数据集群

服务层还存储对象定义和结构的元数据,包括数据库对象的 DDL(数据定义语言)以及列列表、数据类型(包括视图的)和约束等详细信息。这些 DDL 详细信息可以通过 SQL 函数(如 describeget_ddl)检索,或者直接查询 INFORMATION_SCHEMA。前者由服务层自动处理,不需要运行仓库,而后者则需要活跃的仓库并消耗信用。

查询结果缓存

Snowflake 账户中的所有查询结果会由服务层保存 24 小时,供其他用户重用。引用缓存的结果会重置 24 小时时钟,但最长持续时间为 31 天,之后结果会被清除。除了访问权限外,还有其他条件需要满足以确保缓存结果可以重用,包括:

  • 查询必须语法等效
  • 未使用动态函数(如 current_date()
  • 底层表中的数据没有变化
  • 用户拥有访问底层数据源的必要权限

从查询缓存中获取结果远比重新计算更优,因为操作是瞬时完成的,不消耗任何计算信用。与传统数据库不同,在传统数据库中,缓存可能因内存需求而被牺牲,或者因集群挂起而丢失,而 Snowflake 的查询结果缓存会在前述条件下持续保留,直到被清除。

理解查询结果缓存对于高效使用 Snowflake 资源和设计决策至关重要。然而,这并不是用户可以利用的唯一缓存机制。

仓库缓存(Warehouse Cache)

当虚拟仓库从中央存储层(如 AWS S3 存储桶、Azure 容器或 Google 存储容器等云存储中的远程磁盘)访问数据时,数据会被读取到仓库缓存中(由 SSD 存储实现)。SSD 存储的容量取决于仓库的大小。

从 SSD 存储读取数据比从远程磁盘读取数据更快,查询优化器(即服务层)会优先尝试使用缓存,然后再选择从远程存储读取。然而,与服务层缓存不同,仓库缓存有两个显著区别:

  1. 缓存仅针对特定的虚拟仓库。
  2. 挂起(suspend)仓库会清除其缓存。

因此,访问相同数据源的用户可以通过共享同一个仓库来受益。然而,需要权衡保持仓库活跃以保留缓存所需的信用成本与从远程存储重新读取数据所需的 I/O 开销之间的利弊。

当查询无法命中前面提到的任何缓存时,Snowflake 必须访问存储层来执行操作。


存储层

Snowflake 将数据存储在托管账户所在的底层云平台文件系统的远程磁盘上。从远程磁盘读取数据的效率低于从仓库缓存(存储在 SSD 驱动器上)读取,且远低于获取预计算的结果。存储层本身没有缓存可用,因此当没有可用缓存时,它是最后的选择。

总结

Snowflake 的混合云原生设计从零开始为云环境构建,支持实时数据共享和按需工作负载扩展,为用户提供了无与伦比的灵活性,同时克服了传统数据库架构的许多可扩展性限制。Snowflake 的架构可以在不同地区和云提供商之间实现安全的数据共享,其速度与同一账户内数据库之间的数据共享一样快。

通过理解 Snowflake 云架构的三个层次(存储层、计算层和服务层),我们深入了解了这些层次如何支持强大的功能,如零复制克隆(Zero-Copy Cloning)时间旅行(Time Travel)Hybrid Unistore 表以及混合事务/分析处理(HTAP) 表,并且如何实现与半结构化和非结构化数据的交互。

本章还概述了 Snowflake 三层架构的成本及其控制方法。此外,我们讨论了 Snowflake 架构中的各种缓存机制如何协同工作以节省成本并提升性能。

凭借众多革命性功能,Snowflake 不仅仅将自己视为一个数据库,而是一个数据云(Data Cloud) 。考虑到其功能所支持的服务(如数据和应用市场),不难理解为什么需要一个新的术语来描述它。


现在我们已经对 Snowflake 的工作原理有了初步了解,是时候深入探讨其数据库对象的内部机制了。在下一章中,我们将研究 Snowflake 表及其各种类型和参数,以及其他可以用作数据源并作为数据库设计一部分建模的对象类型。理解这些对象及其独特功能将帮助您设计可扩展且高效的数据库架构,充分利用 Snowflake 提供的所有工具。


进一步阅读

关于 Snowflake 所有功能和对象类型的权威指南(标题中就这么写了!),涵盖本书中未涉及的建模相关内容,可参考 Joyce Avila 编写的这本优秀且全面的参考书:

Avila, Joyce. Snowflake: The Definitive Guide: Architecting, Designing, and Deploying on the Snowflake Data Cloud. O’Reilly Media, 2022.