理解 Snowflake 如何运作有助于您制定在 Snowflake 数据云中实现自己贡献的战略。Snowflake 针对数据仓库进行了优化,但并不适合 OLTP(联机事务处理)。本章清楚地解释了这一点。如果您对微分区(micro-partitions)感兴趣,可以自行搜索了解更多。
本书早期提供的信息旨在澄清在您逐步执行后续章节中示例代码时,“幕后”发生的事情。本章开始深入探讨一些技术细节,重点关注一些不太显而易见的内容。我也尝试以足够高的层次提供信息,以满足那些好奇的读者,解答关于“什么、如何、为什么”的问题,并进一步深入到一些鲜为人知且理解较少的 Snowflake 部分,满足那些对技术深感兴趣的读者。
需要指出的是,本章并不打算提供全面的产品介绍。它是基于我学习 Snowflake 的经验以及之前对 Oracle 的知识编写的。因此,本章应该在扩展您现有技术知识、将其延伸到 Snowflake 提供的新范式的背景下阅读,同时挖掘出我在回顾时认为在学习 Snowflake 过程中本应受益的那些信息。
理解 Snowflake 如何从基础构建,充分利用云计算能力,将有助于您后续理解我们如何与 Snowflake 数据云进行集成。
Snowflake 服务
我们开始对 Snowflake 架构的调查,就像几乎所有其他 Snowflake 入门介绍一样——通过检查 Snowflake 实现的三个独立层次:云服务、多集群计算和集中存储。每个层次为 Snowflake 提供不同的功能和能力。我们将分别检查每一层。Snowflake 在其官方网站上介绍了其关键概念,网址为:docs.snowflake.com/en/user-gui…
存储和计算的分离是 Snowflake 与其竞争对手的独特区别。随着本章的展开,您将了解到这一基本架构差异如何成为一个颠覆性的游戏规则改变者。
一个重要的要点是云无关层(cloud agnostic layer)。Snowflake 客户可以选择托管 Snowflake VPC 的三个支持的云平台之一(AWS、Azure、Google Cloud)。尽管所有云平台提供相同的能力,但截至本书编写时,GCP 在物理区域可用性和产品功能实现方面稍微落后于 AWS 和 Azure。Snowflake 状态网站不仅指示了 Snowflake 的操作状态,还显示了物理区域的可用性(请参见 status.snowflake.com)。
我们也没有被限制在单一的云服务提供商(CSP)中。我们可以将 Snowflake 托管在所有三个云平台中,并在它们之间无缝地移动数据。稍后,您会看到在不同 CSP 之间移动数据可能会出现一些潜在问题。我们也可能希望在两个或所有三个 CSP 中平衡服务供应,以降低应用集中风险或数据引力对单一云提供商的依赖。
本书的大部分内容基于 AWS,因为这是我的主要专长所在。几乎所有的书面材料都是可迁移的。您可以将 Azure Blob Storage 或 Google Cloud Storage 替换为 Amazon Simple Storage Service(Amazon S3)。稍后我们写一些代码时需要做语法上的调整,但这些问题应该是容易理解并解决的。
Snowflake 架构是共享磁盘和共享无架构的混合体,具有一个集中存储库,用于存储持久化数据,并且可以通过帐户中的所有多集群计算节点访问,如图 3-1 所示。这意味着您的数据始终可以在一致的状态下进行处理,同时每个计算节点独立操作。
云服务层
云服务(参考链接)提供了跨所有 Snowflake 活动的协调服务,包括访问控制、身份验证(谁可以登录,能做什么)、基础设施管理、元数据管理、查询编译、查询计划和查询优化等功能。
多集群计算
多集群计算,也称为虚拟仓库(参考链接),允许我们选择分配给处理查询的处理器数量和内存大小。Snowflake 的方法与我们组织中许多熟悉的数据库,如 Oracle 和 SQL Server,形成鲜明对比,这些数据库的处理器和内存是固定的。Snowflake 提供高度可扩展性,可以选择不同规模的仓库模板,包括集群选项。Snowflake 在需要时按需提供所需的性能,并根据我们为仓库设置的参数自动扩展,当我们的工作负载增加时,系统会自动扩展。
注意 每个 Snowflake 仓库都是一个命名的包装器,代表一个由 CPU、内存和临时存储(SSD)组成的服务器集群。所有查询都需要声明仓库。能够从缓存或元数据中获取结果的查询不会消耗 Snowflake 积分。所有其他查询调用会消耗 Snowflake 积分。更多信息请参见此链接。
数据库存储
数据库存储对应于 CSP 基础存储(Amazon S3、Azure Blob Storage、Google Cloud Storage)。无论选择哪种云提供商,Snowflake 都会通过 SQL 透明地管理所有存储交互,以支持数据仓库的核心操作。更多信息请参见此链接。
Snowflake 从云提供商传递的存储费用根据区域和云提供商有所不同,AWS 上的大致费用为每 TB 约 $23。需要注意的是,Time Travel 和 Fail-safe 功能会产生额外的存储费用。
稍后,您将了解如何查看数据库对象的底层存储,但现在,知道 Snowflake 使用我们选择的云提供商存储来以高度安全的方式存储我们的数据就足够了。从我们登录的那一刻起,几乎是无限的存储空间始终可用,无需向 Snowflake 请求更多存储。
Snowflake 配置
Snowflake 首先在三个支持的云平台(AWS、Azure 和 GCP)中,在不同的物理位置建立其技术足迹。有关详细信息,请参阅以下链接:
对于 AWS 和 Azure,配置的 Snowflake 账户在功能上是等效的,某些命令的语法可能有所不同。截至本书编写时,GCP 上的 Snowflake 账户功能落后于 AWS 和 Azure。然而,所有 Snowflake 账户都是按照统一模式进行配置的,如图 3-2 所示。
图 3-2 中的一些线索稍后有助于我们的理解。首先,存储位于多租户集群之外,但仍在 Snowflake 部署中,这意味着存储管理不再依赖单一的 Snowflake 账户,而是可以跨多个 Snowflake 账户共享存储。这种方法支撑了共享功能。第二,元数据存储保存在一个键值对存储库中,支持全局服务层,接下来将讨论。最后,图中标明了虚拟仓库(即您的 Snowflake 账户),这一点将在接下来的部分中讨论。它是我们 Snowflake 配置中可用的最高级容器。
全局服务层
支撑 Snowflake 并实现全局服务层的是 FoundationDB,这是一个开源的键值数据存储系统,适合高性能读写和数据操作,特别适用于 OLTP 风格的数据管理。FoundationDB 存储了我们的 Snowflake 账户元数据,即有关每个对象、关系和安全特性的所有信息,这些元数据形成了我们账户的目录,记录和描述了账户的内容。无论选择哪种云提供商,全局服务层的实现对于所有云平台都是一致的,从而确保了 Snowflake 的互操作性。
我们不时需要访问全局服务层。例如,一些应用开发功能(如安全监控)只有在能够以编程方式访问元数据时,才能通过元数据驱动。我将在第 6 章中进一步解释这一点,深入探讨技术细节。
不仅是为了应用程序编程需求,我们还需要访问全局服务层,Snowflake 的功能也依赖于元数据来驱动内置功能。Snowflake 的各个方面都依赖于 FoundationDB,因此我们必须了解如何使用可用的工具与元数据进行交互。
安全监控在第 4 章中有详细介绍,但我现在想简要讨论一下。FoundationDB 的元数据通过 SQL 命令(如 LIST、SHOW 和 DESCRIBE)暴露到 Snowflake 中。这些命令不会返回其他 SQL 命令可用的记录集,因此无法基于 SHOW 命令的输出创建视图。相反,我们必须横向思考,使用 JavaScript 存储过程、RESULT_SCAN 和本地表将最后一次查询的输出转换为可用的记录集。请注意,这种方法只是一个时间点的解决方案,并且存在潜在的陷阱,可能会让不小心的人出错。现在,了解访问全局服务层时在 SQL 中存在一些摩擦已经足够,稍后你会看到如何解决这些挑战。
Snowhouse
Snowhouse 是 Snowflake 用来监控和管理自身的内部工具,并提供有关使用遥测的内部指标。
注意: Snowflake 员工无法通过 Snowhouse 绕过账户安全措施,因此您的数据始终保持安全。
Snowhouse 将每个组织的账户元数据与其他 Snowflake 内部系统的数据(从销售和营销到基础设施监控工具)结合,提供每个账户使用情况的全景视图。作为一个内部管理工具,Snowhouse 被销售支持工程师用于识别消费高峰、调查底层 SQL 性能问题,以及云提供商虚拟机配置和性能等。
Snowflake 是 Snowflake 最大的用户,这对于考虑将 Snowflake 作为数据云的所有人来说,具有增强信任的作用,因此,如果您的 Snowflake 支持团队联系您,所传递的信息是基于充分的证据和合理推理的。与其他供应商相比,Snowflake 支持团队的主动性值得关注,您可以自行做出结论。
当然,作为 Snowflake 服务的最终消费者,我们无法访问 Snowhouse,因此这一部分仅供参考。
Snowgrid
Snowgrid 是一个术语,您很快就会更多地听到。它是 Snowflake 的一项内部技术,支撑了透明的数据共享,不论云提供商和物理位置如何。
高可用性(HA)
在每个地区(或地理位置),每个云服务提供商(CSP)都会在三个地理上分离的可用区中实现其核心功能,这些可用区是分隔但互联的。Snowflake 继承了底层 CSP 架构,作为在某一地区部署的产品,如图 3-3 所示。在幕后,Snowflake 会在(近乎)实时地复制变更,对最终用户透明且无缝操作。每个环境都提供了弹性,并且构建了同步复制。我们无法看到我们的账户托管在哪个可用区,只需接受已提供的服务即可。
我们不会讨论营销噱头或关于 99.999999999% 数据耐久性(发生战争行为可能对您的数据产生更大影响)或 99.99% 可用性(每年不到一小时的停机时间)的分析,但还是提醒您注意这些指标,无论是云服务提供商给出的报价,还是您希望进一步调查的内容。
通过三个可用区,以及不可变的微分区方法(稍后讨论),Snowflake 保护了多种场景,包括以下情况:
- 客户错误:包括意外删除数据和对象、加载一个或多个带有错误数据的数据文件,或加载数据的顺序错误。
- 虚拟机故障:包括为关键云服务提供三重冗余、自动重试失败的查询部分。
- 单个可用区故障:包括 AWS 上的多个可用区和 Azure 上的多个可用集。如果发生故障,Snowflake 的服务可能会降级,因为负载均衡会跨一个或两个可用区进行调整,具体取决于故障的性质。
- 区域故障:包括在某个区域内的服务丧失,跨区域数据库复制,以及故障切换。
- 多区域故障:包括在多个区域内的服务丧失,跨区域数据库复制,以及故障切换。
区域故障的根本原因更可能是 Snowflake 核心服务提供的中断,而非整个云服务提供商(CSP)基础设施的故障。Snowflake 实时服务状态可通过 status.snowflake.com 查看。
补丁和维护
每个 Snowflake 实例都会自动打补丁并更新,且在没有停机时间的情况下进行,对账户透明,通过逐步发布的过程进行。在此过程中,Snowflake 更新首先会应用于提前访问账户,比标准账户提前 24 小时,最后应用到企业账户及以上账户。
偶尔,Snowflake 会进行功能更改。这些更改会提前通知,通常意义不大。然而,对于那些幸运地在拥有专职 Snowflake 支持人员或支持合同的大公司工作的用户来说,通常会收到周期性邮件,提前通知即将到来的更改。
有关 Snowflake 发布的更多信息,请访问 docs.snowflake.com/en/user-gui…。第 4 章会详细介绍如何启用和禁用行为更改发布,以便在部署之前进行测试。
创建试用账户
获得最大价值的方法是亲自动手实践。实践出真知,虽然重复输入命令可能很枯燥,但这种做法有助于加深记忆。然而,要想输入命令,您必须拥有一个 Snowflake 账户进行练习。请访问 www.snowflake.com,点击“免费开始”按钮,填写一些必要的细节,以启动 30 天的免费试用账户。
注意:请确保选择“Business Critical Edition”版本,因为您的组织可能会使用此版本。
我们在本书中依赖某些功能,因此,成功地完成示例代码的实践时,Business Critical Edition 至关重要。我并不会覆盖每个功能(必须留下一些内容让您自己去发现!),但有些功能对我们的理解至关重要,尤其是与安全相关的功能。图 3-4 展示了每个 Snowflake 版本中可用的功能。
本书中的所有示例都是使用 AWS 上的试用账户进行测试的,因此,我推荐将 AWS 作为首选平台。如果您选择其他平台,效果可能会有所不同。
组织
直到最近,每个 Snowflake 账户都是在与 Snowflake 技术代表的协调下创建的。现在,Snowflake 引入了一个名为“组织(Organizations)”的新功能,它提供了高度自助服务的功能,便于在公司所有 Snowflake 账户之间进行管理。第 4 章将详细讨论“组织”功能,但目前只需注意,使用 ORGADMIN 角色,您可以集中管理公司内所有账户,无论账户所在的地点和云提供商(Cloud Provider)如何。
账户
之前已经讨论过 Snowflake 账户。图 3-2 中将虚拟仓库(virtual warehouse)视为 Snowflake 账户的同义词。接下来,我们将解释一个账户包含的内容,以及每一层提供的功能。我们可以将账户视为容器的最高级别和 Snowflake 配置环境的最外层边界。虚拟仓库在图 3-2 中被标识为 Snowflake 账户。
Snowflake 账户有两种计费方式。按需计费(On Demand)是按使用量付费的选项,每个信用(credit)有固定的价格。相比之下,容量合同(Capacity contract)是预先购买的批量信用,通常是按照固定期限进行购买的。根据本书的写作时间,每个信用的费用为 $5,并且如果批量购买会有折扣。有关此主题的更详细讨论超出了本书的范围。有关详细信息,请与您的 Snowflake 销售代表联系。Snowflake 信用的详细解释可见于 docs.snowflake.com/en/user-gui…。
云服务层
云服务层是一个功能套件,协调 Snowflake 中的各项活动,以处理用户请求,从登录到查询调度。云服务层运行在 Snowflake 从云提供商处配置的计算实例上。元数据操作不使用计算资源,云服务仅在消费超过每日计算资源消费的 10% 时才会收费。云服务层提供了多个服务,下面逐一讨论。
认证和访问控制
认证是验证尝试访问 Snowflake 的行为主体身份的过程。行为主体可以是一个具名的个人用户,也可以是用于系统间互联的通用服务用户。
Snowflake 支持通过 Duo 进行多因素认证,这是一项可选择的功能,所有用户都可以启用。
访问控制通过网络策略来执行,网络策略可以被看作是环绕您 Snowflake 账户的一个防护墙,允许从各种终端访问您的环境,并且可以在账户级别配置。我将在第 4 章讨论如何设置网络策略以及如何有效监控这些策略。
基础设施管理
基础设施管理包括动态(弹性)分配和释放资源的过程,这样可以根据所有用户和工作负载的需求精确地分配所需的资源,开发人员和用户可以专注于实现功能和业务价值,而不必被运行时环境问题所分心。
元数据管理
元数据存储库使用 FoundationDB 来存储表定义、每个对象的所有微分区文件引用、数据保留窗口内表数据的所有版本追踪信息以及各种统计信息。元数据管理服务提供查询优化、编译、规划和安全功能。
查询优化
Snowflake 的查询优化器通过在元数据缓存中进行静态修剪,基于查询谓词消除微分区。然后,过滤器使用元数据确定要处理的确切数据。
当结果集可以通过缓存满足时,记录将从结果集缓存中返回。
对于好奇的人,元数据缓存保存着几组统计信息:
- 表:行数、表的字节大小、文件引用、表版本
- 微分区:最大/最小值范围、不同值的数量、NULL 计数
- 聚类:微分区总数、微分区重叠值、微分区深度
这些统计信息用于性能调优,相关内容将在第 11 章中讨论。动态修剪发生在仓库缓存中,这将在本章后续部分讲解。
结果缓存
结果缓存存储所有仓库执行的查询结果,缓存的保留期为 24 小时。每当执行精确匹配的查询时,结果集过期计时器将重置,保留期将延长 24 小时,除非底层数据已发生更改。结果集的最大保留时长为 31 天,之后会被自动清除,随后执行查询时需要重新加载缓存数据。
虚拟仓库
虚拟仓库也被称为多集群计算。每个虚拟仓库是一个命名的包装器,封装了一组(或集群)服务器,包含多核/超线程 CPU、内存和临时存储(SSD)。仓库是自我调优的大规模并行处理(MPP)引擎。
仓库运行时是 Snowflake 盈利的关键,因此必须特别关注合理配置和参数设置,尤其是自动挂起(auto-suspend)。并非所有查询都需要运行中的仓库,因为一些查询可以直接从元数据或查询缓存中获得结果,但对于那些确实需要运行仓库的查询,如果仓库尚未启动,系统将实例化仓库;也就是说,云服务层将配置正确数量的服务器(包括 CPU、内存和 SSD 缓存),以满足仓库配置并开始执行查询。
Snowflake 在每个可用区域内维护多个仓库,以减少按需启动时间。通过 Snowhouse 的统计分析,Snowflake 能够准确预测使用情况,但对于新区域,尚未建立使用模式时,预测的准确性较差;因此,可能会遇到超过 10 秒的配置延迟。随着使用模式的演变,预测会变得更加准确。
仓库的最短运行时间为 1 分钟,之后按秒计费。仓库可以通过命令行或用户界面手动创建和管理。
注意:请确保所有仓库的自动挂起时间最初设置为 1 分钟。
偶尔仓库在启动时无法正常配置。Snowflake 会检测到故障并自动尝试修复失败的资源。当请求的资源达到 50% 或更多时,SQL 语句将开始处理。
没有一个标准答案来确定最佳的仓库配置,必须进行适当的测试。虽然仓库扩展提供了许多解答,但其他性能选项,特别是对于大数据集的考虑,稍后在本章中将进一步讨论。我们可以说,根据执行的活动类型,所需的仓库配置会有所不同。数据加载和查询有不同的工作负载特性,因此必须根据这些特性来调整配置。
总的来说,以下原则适用于仓库配置的调整:
- 横向扩展(Scale up) :增加仓库的规模(T-shirt size),以提高查询性能、处理更多数据、执行更复杂的查询。
- 纵向扩展(Scale out) :增加集群数量,以并行运行更多查询,支持更多用户。
- 跨仓库扩展(Scale across) :声明更多仓库,以隔离不同规模的工作负载,避免资源争用。
单个仓库并发性
注意:此部分包含关于底层云提供商 CPU 硬件(如 AWS EC2、Azure VM)的合理假设。实际使用时,结果可能会有所不同。
一个 X-small 的仓库配置了一个包含 CPU、内存和 SSD 存储的单个服务器。我们无法识别实际的硬件配置——在云环境中这本不应是问题。然而,在配置仓库时,有一个方面是与底层硬件密切相关的:CPU 配置。
CPU 不再是一个单一的整体硅芯片,能够处理单一任务。相反,CPU 现在有多个核心,每个核心可以处理两个或更多的并发线程。为了讨论的方便,假设单个 CPU 有四个核心,每个核心有两个线程,因此总共有 16 个并发线程,如图 3-5 所示。
尽管每台服务器可能总共具有 16 个可用线程,但显然每台服务器还必须保留足够的能力来执行其他服务,包括其自身的操作系统。因此,我们进一步假设,在任何时候,Snowflake 实际可用的 CPU 核心数为建议的八个核心中的四个。
Snowflake 高级 SQL 课程表明,每个集群中的每台服务器有八个并发线程可以用于处理查询。当仓库的查询需求超过八个并发执行请求时,并且启用了集群功能,另一个同样大小的仓库集群会被实例化,提供额外的八个并发线程。最多可以并发实例化 10 个集群,从而为单个 X-small 仓库声明提供最多 80 个线程。当最后一个正在执行 SQL 语句的线程停止工作时,活动集群会缩减,这取决于自动挂起设置,并且不在最大化模式下运行。
我们来看一个替代的视角。X-small 仓库中有八个核心,其中我们假设四个核心可供 Snowflake 使用。当查询提交到该仓库时,Snowflake 会尝试将查询分成四个部分。每个核心尝试扫描表的一部分。请注意,这个建议是理想的;查询必须是可拆分的,并且仓库的核心必须可用于并行化。
对于那些希望深入了解并发性的用户,我建议查看 MAX_CONCURRENCY_LEVEL 参数,更多信息请访问 Snowflake 官方文档,以及 Subhrajit Bandyopadhyay 在 LinkedIn 博客 上的相关文章。
扩展
仓库是通过内置模板定义的,T-shirt 尺码范围从 X-small(一个服务器)到 6XL(512 个服务器),这被称为“向上”或“向下”扩展。每增加一个 T-shirt 尺码,实例化的服务器数量会翻倍。仓库可以动态调整大小;T-shirt 尺码集群可以根据需要在命令行中更改。仓库也可以在会话中手动挂起。
另外一个选项(是我首选的方式)是声明多个仓库,并使用最适合当前工作负载的仓库。这叫做“横向扩展与回退”。你可能会问,为什么作者偏好这种方法?首先,如果一个调整大小的过程失败了,仓库会保留调整后的声明直到下次调用,这可能是不适合且成本高昂的。其次,对于工作负载隔离、可重复的性能调优、确定用于计费的信用消耗,以及保持一致的系统配置视角,静态的仓库声明是更合适的选择。第三,重新声明的仓库实例会在旧仓库停用时短暂运行,对于较大的仓库来说,这可能会很昂贵。第四,我们的数据仓库是复杂且不断扩展的环境。多个仓库声明能够提供更好的工作负载隔离。
仓库也可以进行集群化。可以在仓库配置中声明多个相同 T-shirt 尺码的实例,并在负载增加时由 Snowflake 动态实例化。当负载减少时,它会自动关闭。这叫做“横向扩展与回退”。同样,仓库可以通过将最小和最大集群数量设置为相同的值(大于 1)来运行在最大化模式下,在这种情况下,所有集群会在仓库启动时自动实例化。
仓库集群始终是相同类型的集群。无法在单一仓库声明中选择不同的 T-shirt 尺码。图 3-6 显示了实例化的集群数量以及每小时的信用消耗,这有助于我们配置仓库。稍后我会讨论如何监控信用消耗。
对于加载十亿行数据的单个大型查询,图 3-7 显示了扩展的效果。增加仓库的大小可以改善响应时间,但如果仓库大小过大,最终会导致成本增加。仓库大小的选择及其相关成本必须通过具有代表性的工作负载配置进行测试,注意多个仓库可以(且应该)声明,并根据目标工作负载选择最合适的仓库配置。
从图 3-7 中的重要启示是,扩展性是线性的,直到查询不再受资源限制为止。
扩展策略是影响多集群仓库行为的最终仓库参数,可以是标准(默认)或经济型。然而,已弃用的扩展策略“Legacy”也存在;其行为已更改为标准,因此不应再使用。扩展策略影响何时实例化或关闭集群。有关更多信息,请参阅文档:设置多集群仓库的扩展策略。
查询处理
Snowflake 查询处理引擎使用本地 SQL。一个 Snowflake 会话一次只能有一个仓库在运行,可以更改或重新调整大小,注意之前提到的重新调整仓库大小的影响。
仓库缓存
在后台,Snowflake 维护一个准备好运行的仓库池。这解释了为什么 Snowflake 在重新初始化一个暂停的仓库时,会尽量恢复原始缓存,尽管不能保证一定会发生这种情况。由于缓存恢复不能保证,最低的期望是仓库暂停时会清除缓存。缓存恢复是一种附加好处。
仓库缓存是特定于每个仓库的,不会与其他仓库共享。仓库缓存的清除没有固定的时间表。如果一个仓库始终在运行,其缓存将永远不会被清除。这对重复查询可能是一个有吸引力的性能选项。然而,在实施之前,我建议进行实验和彻底测试,因为在仓库运行的第一分钟之后,每秒都会消耗积分。
重新调整仓库大小会导致新服务器的提供。因此,调整大小的仓库会清除缓存。这个行为是基于前面解释的,当仓库调整大小时,可能会导致额外的积分消耗,因为新服务器会被实例化——这也是不建议重新调整仓库大小的原因之一。
如果相同(即区分大小写的)SQL 文本/查询被重新发出,缓存将被重用,除非 Snowflake 缓存由于底层数据更改而失效,确保查询始终返回最新的数据。
查询分析
查询分析可以应用于已执行完毕的查询和正在执行的查询。个人资料只能在用户界面中查看,无法通过编程方式提取当前信息进行外部工具分析。
查询分析的详细调查和解释超出了本书的范围。然而,我将在第 11 章讨论基本原理。进一步的信息请参考:Snowsight 活动监控,并注意 Snowsight 的使用。
监控
经典用户界面提供了一个监控仓库负载的屏幕,如图 3-8 所示。
选择一个单独的仓库可以查看过去 14 天的使用情况,如图 3-9 所示。
稍后,我将解释如何从 Snowflake 账户使用情况存储中提取仓库利用率信息和信用消耗情况,以便识别信用消耗。但目前,了解 Snowflake 提供了监控工具就足够了。
存储
支持每个 Snowflake 实现的基础是存储,即数据存放并持久化的物理位置。我们讨论的重点更多地集中在 AWS 平台,因此可以将 Azure Blob 存储或 Google Cloud 存储替换为 Amazon S3。
与以往的数据库不同,Snowflake 免除了在安装时手动配置存储的烦恼,不再需要配置存储区域网络(SAN)或网络附加存储(NAS),也不再会出现由于磁盘空间不足导致数据库挂起或事务失败的情况,云存储的弹性特性确保磁盘始终可用,随需应变,按需提供。更重要的是,由于 Snowflake 采用了创新的方式,我们不再需要像其他数据库供应商那样担心事务管理的问题——不再需要回滚、撤销、行链接或将表空间分开存储到不同的物理磁盘上。
为了回应我们网络安全同仁的要求,我们必须始终确保外部存储在未经授权的情况下得到适当的安全保护,通过实施合适的安全策略并经过验证测试,确保安全策略的有效性。
不同平台,不同方法
我们必须问自己,为什么 Snowflake 采用了他们所选择的方法。Snowflake 是一个数据仓库,而不是一个在线事务处理(OLTP)数据库,因此存储考虑有所不同。
答案的一部分在于云服务存储提供的本质差异。我们不再需要将数据容器划分为不同的逻辑组。Snowflake 本可以强制实行类似的容器管理,但这个概念已经不再适用。此外,数据仓库通常是大多数历史数据库供应商产品的扩展,而非初始的架构设计或核心能力。数据仓库可能并非最初设计的核心功能。而随着市场的成熟,数据量、速度和多样性爆炸性增长,数据仓库现已成为严肃数据分析的必要条件,因此需要一种不同的方法。Snowflake 将自己定位为数据仓库供应商,因此启用了不同的存储管理范式,接下来将详细讨论。
微分区与集群键
Snowflake 通过微分区来实现存储,微分区是构成逻辑表的基础存储单元。每个微分区包含最多 16 MB 的数据,这些数据使用专有的压缩算法进行压缩。未压缩时,每个微分区包含 50 MB 到 500 MB 的数据,数据以混合列式格式组织,根据列的数据类型优化压缩。
包含行数、表大小(字节)、物理文件引用、表版本和区域映射信息的对象元数据会根据 Snowflake 版本和指定的保留期保留所有已写入的微分区(数据保护将在本章后续部分讨论)。对于每个微分区,元数据将保留最大值和最小值范围、不同值的数量以及 NULL 值计数。如果为单个对象写入多个微分区,则元数据包括微分区的总数、重叠深度和重叠值。我会在后面简要讨论如何使用元数据,但请注意,深入探讨 Snowflake 性能调优超出了本书的范围,因为这是一个重要的主题。
传统数据库供应商的磁盘管理策略是可变对象存储;对象的内容会根据数据操作语言(DML)操作(如插入、更新和删除)发生变化,对象的大小会动态调整,导致存储容器变为可变的。数据的变化和索引的变化会导致磁盘管理的主动监控和人工/机器干预。Snowflake 的方法则不同;一旦磁盘结构(微分区)被写入,它就变得不可变。DML 操作会导致创建新的微分区,而微分区一旦写入,就无法再进行物理管理,除非修改集群键,否则无法影响其行为。
理解可变与不可变存储管理的区别,是理解为什么 OLTP 不是 Snowflake 的合适用例的关键。对于单个记录操作的微分区管理可能会导致排队。在高频率 DML 场景中,存储无法跟上,可能导致事务失败。然而,通过使用临时表来合并 OLTP 数据,并随后将数据批量加载到永久表中,可能会提供一种可接受的模式,前提是失败时的错误处理允许重新执行。这只是一个建议。
注意:将 Snowflake 用于数据仓库,而非 OLTP。
图 3-10 说明了一个包含三个微分区的表,并对英国数据集进行 DML 操作,导致创建新的微分区。我们将在本章中进一步探讨这一主题。
Snowflake 微分区方法的影响是巨大的。在初始数据加载时,Snowflake 会自动将数据按微分区聚类,而不对数据做任何假设。不会应用直方图或其他算法,每个微分区都会被写入,并捕获元数据。默认方法对于大多数场景都能很好地工作,特别是对于小于 1 TB 的数据加载,查询性能通常没有问题。
然而,随着时间的推移,当数据经过 DML 操作或数据量超过 1 TB 时,可能会观察到性能下降或初始性能较差。在这种情况下,数据可能没有根据最常用的查询谓词(用于访问微分区)在表中进行最佳聚类。我们可以选择添加聚类键,指定一组列或表达式,专门设计以匹配最常用的查询谓词。需要认识到“一刀切”的做法并不适用,某些查询谓词的数据访问路径可能会受到影响,Snowflake 提供了物化视图,可以应用不同的聚类策略。在不同的场景下,结果会有所不同。
Snowflake 提供了自动聚类功能,监控聚类表的状态,并在适当时自动重新聚类,但仅适用于已声明聚类键的表。手动重新聚类已经被废弃,因此不应再考虑这种做法。并非所有场景都推荐添加聚类键,应该进行性能测试,以验证任何更改在发布到生产环境之前的好处。
微分区支持水平和垂直分区修剪,在元数据缓存中执行静态修剪,只包含与查询谓词匹配的微分区。动态修剪发生在查询执行时,根据联接条件和其他构造进行。这一方法解释了聚类键和数据存储的重要性。
尽管我稍后会讨论我们在云存储中的数据如何得到保护,但需要注意的是,所有 Snowflake 客户的数据默认都会使用最新的安全标准和最佳实践进行加密。Snowflake 使用强 AES 256 位加密,并采用基于硬件安全模块的分层密钥模型。Snowflake 服务会定期轮换密钥,数据也可以定期重新加密(重新键控)。数据加密和密钥管理是完全透明的,无需配置或管理。有关详细信息,请参见 Snowflake 加密和密钥管理文档。
索引与约束
Snowflake 不支持将单独的索引作为对象存储在主表之外。虽然可以声明唯一键、主键和外键约束,但 Snowflake 不会强制执行这些约束,也不会创建相应的对象。声明这些约束有助于数据自发现工具,允许自动创建实体关系图。唯一强制执行的约束是 NOT NULL。
对于具有传统 RDBMS 背景并拥有丰富数据仓库经验的人来说,最初看不到强制约束可能显得有些反直觉,甚至是倒退的步骤。
在开发 Snowflake 应用程序时,我们面临着思维方式的挑战,因为我们通常期望在数据仓库环境中数据在源头上是干净的。相比之下,在 OLTP 环境中,我们期望在数据进入数据库之前进行验证。如果我们接受这一原则,那么我们的数据仓库不应允许本地更新数据,所有数据的变更必须在源头进行。缺少强制约束变得不再重要,重要的是这些约束本身的声明。此外,假设我们的数据仓库摄取策略包括识别数据质量问题的机制,但不会排除任何数据,无论其质量如何,那么我们就有一个自动机制,能够将数据差异反馈到源系统,关闭反馈循环,并随着时间推移衡量数据质量。
物化视图
与其他 RDBMS 平台一样,Snowflake 在企业版及更高版本中支持物化视图。我们可能会出于各种原因选择实现物化视图。本节关注的是微分区,而非更广泛的性能调优问题,考虑到微分区修剪在查询性能中起着重要作用。
物化视图通过后续章节讨论的无服务器计算资源进行维护。目前,了解微分区维护由 Snowflake 处理,并根据使用情况收费即可。我们只需声明物化视图,并定义新的聚类键。Snowflake 会处理所有的维护工作。
注意:物化视图没有 Time Travel 功能。
与其他 RDBMS 比较时,Snowflake 物化视图有几个限制。最显著的限制是只能引用单个表。物化视图不能引用其他物化视图。所有限制详情请参见 Snowflake 物化视图文档。
讨论为什么我们要实现物化视图的全部原因超出了本书的范围,因为这些答案涉及性能调优和查询优化。关键点是我们可以通过重新聚类重新定义表,从而支持不同的最佳访问路径。
阶段(Stages)
存储也被称为“阶段”(stage)。稍后我将展示如何通过存储集成在我们的 AWS 账户中映射 S3 存储,这与关联的 AWS 账户配置一起建立信任关系,提供四种存储类型中的第一种,称为 外部阶段(external stage) 。
我们还提到过在 Snowflake 账户中映射的 S3 存储,在这种情况下无需进行 AWS 配置,这种存储被称为 内部阶段(internal stage) 、命名阶段(named stage) 或 内部命名阶段(internal named stage) 。这三种标签是可以互换使用的,通常在 Snowflake 边界外不可访问。需要注意的是,未来将开发功能使得内部阶段可以被访问。当数据通过 PUT 命令传输到内部阶段时,数据会在本地机器上加密,然后才传输到内部阶段,以确保数据传输生命周期中的安全性。
一些对象类型,如表(tables)和物化视图(materialized views),需要存储空间。它们会消耗 Snowflake 账户中的 S3 存储。这些被称为 表阶段(table stages) ,每个对象都有一个唯一命名的阶段。
最后,用户阶段(user stages)支撑着用户界面。它们不应被直接引用。它们也会消耗我们账户中的存储。
注意:对于外部阶段,请在将其投入生产前应用并测试您的安全策略。
图 3-11 说明了阶段的物理位置,后续章节会对此进行详细讨论。
数据共享(Shares)
第1章讨论了安全的直接数据共享(Secure Direct Data Share)。现在,您已经了解了微分区的不可变性质以及 Snowflake 如何使用云存储持久化对象,接下来我们将讨论 Snowflake 数据云的第一个集成路径,它基于 Snowgrid,这是 Snowflake 的底层专有数据交换平台。大多数账户默认启用数据共享功能。如果您遇到问题,请联系 Snowflake 支持。
注意:数据共享仅适用于在同一云提供商和区域内的本地账户之间的数据复制。
拥有数据并授予其他人使用权限的一方被称为 提供者。使用数据的一方被称为 消费者。提供者始终控制谁可以访问其数据。Snowflake 的工作人员不能查看、覆盖或控制提供者的数据。被消费的共享对象无法修改或添加,只能查询,不能修改。共享对于消费者来说是只读对象,消费者只能从共享中读取数据,不能执行其他操作。消费者不能通过共享技术将数据分享给其他账户,但他们可以使用数据并将其与自己的数据集进行联接。消费者可以通过从共享中选择数据并共享他们的表来将共享的数据插入到他们的表中。这是数据共享唯一的级联方式。
安全的直接数据共享(Secure Direct Data Sharing)使得您可以将账户中数据库中的选定对象与其他 Snowflake 账户共享,但仅限于同一云提供商和 Snowflake 区域内的提供者和消费者。
对于 Snowflake 客户,计算费用由消费方账户支付。关于非 Snowflake 消费者使用读取账户的问题将在第14章简要讨论。提供者负责支付消费费用。消费者可以为每个共享创建一个数据库。在查询共享之前,必须先创建入站数据库,创建的数据库可以重命名和删除。
最重要的是,没有数据被复制。仅凭元数据即可安全地共享存储中的数据。由于没有从提供者账户复制数据,因此消费者的 Snowflake 账户不会为存储付费。想一想这个含义:零复制、实时事务性数据共享,完全由您控制,推动数据民主化,支持公民科学家。图 3-12 展示了微分区如何共享。
第1章讨论了安全的直接数据共享(Secure Direct Data Share)。现在您已经了解了微分区的不可变性质以及 Snowflake 如何使用云存储持久化对象,接下来我们将讨论基于 Snowgrid 的第一个集成路径,这是 Snowflake 的底层专有数据交换平台。大多数账户默认启用数据共享功能。如果您遇到问题,请联系 Snowflake 支持。
注意:数据共享仅适用于在同一云提供商和区域内的本地账户之间的数据复制。
提供者 是拥有数据并授予其他人使用权限的一方。消费者 是使用数据的一方。提供者始终控制谁可以访问其数据。Snowflake 的工作人员无法查看、覆盖或控制提供者的数据。被消费的共享对象无法修改或添加,只能查询,不能修改。共享对于消费者来说是只读对象,消费者只能从共享中读取数据,不能执行其他操作。消费者不能通过共享技术将数据分享给其他账户,但可以使用数据并将其与自己的数据集进行联接。消费者可以通过从共享中选择数据并共享他们的表来将共享的数据插入到他们的表中。这是数据共享唯一的级联方式。
安全的直接数据共享(Secure Direct Data Sharing)使得您可以将账户中数据库中的选定对象与其他 Snowflake 账户共享,但仅限于同一云提供商和 Snowflake 区域内的提供者和消费者。
对于 Snowflake 客户,计算费用由消费方账户支付。关于非 Snowflake 消费者使用读取账户的问题将在第14章简要讨论。提供者负责支付消费费用。消费者可以为每个共享创建一个数据库。在查询共享之前,必须先创建入站数据库,创建的数据库可以重命名和删除。
最重要的是,没有数据被复制。仅凭元数据即可安全地共享存储中的数据。由于没有从提供者账户复制数据,因此消费者的 Snowflake 账户不会为存储付费。想一想这个含义:零复制、实时事务性数据共享,完全由您控制,推动数据民主化,支持公民科学家。图 3-12 展示了微分区如何共享。
克隆(Cloning)
既然您已经了解了微分区的不可变性质,您可以看到 Snowflake 外部阶段、表、模式和数据库是如何仅通过元数据操作来克隆的,从而实现零复制克隆。克隆对象是一个新的、独立的对象,您可以对其执行与原始对象相同的所有类型的操作。原始的底层微分区保持不变,直到在克隆对象中修改数据。只有当对主对象或克隆对象执行 DML 操作时,才会实例化受影响的微分区,此时会产生存储费用。克隆几乎是即时的,最多几分钟,并且没有克隆对象大小的限制。
一些限制适用。内部命名阶段无法克隆;但是表及其表阶段可以克隆。克隆的外部阶段内容(文件)不会被复制。临时表和瞬态表不能作为永久表克隆。物化视图不能直接克隆,但如果克隆的数据库或模式包含物化视图,则它们会被克隆。另外,请查看文档,了解克隆对象的标签是如何处理的。
注意:数据库克隆仅在单一账户内部可用。模式克隆可用于数据库内。表克隆可用于模式内。
其他克隆对象可能会表现出异常或意外的行为;有关详细信息,请访问 Snowflake克隆文档。最重要的是,在依赖克隆程序之前,一定要进行测试、重新测试,并再次测试,确保在自动化测试用例和用户验收测试环境中考虑到所有边缘情况。
克隆可以在当前时间戳、历史时间戳之前或 SQL 语句标识符之前进行。对于历史对象克隆,所选择的时间点必须在 Time Travel 保留期内,并且在选择的时间点存在。注意,当前角色必须具有适当的源对象授权。请查阅文档以了解详细信息。
克隆数据库可以快速生成与原始环境相同的环境,用于快速测试新代码或作为生成示例数据集的起点,或者用于执行一些以前因传统数据库复制环境所需时间而无法实现的场景。结合 Time Travel 功能,Snowflake 微分区策略的巨大优势变得显而易见。克隆数据库通常是复制的基础,接下来将讨论复制。
复制(Replication)
要启用复制,必须使用 ORGADMIN 或 ACCOUNTADMIN 角色在您的账户中启用此功能。在较大的组织中,ORGADMIN 功能可能已经启用,因此复制可能由中心职能启用;否则,复制可以通过 ACCOUNTADMIN 角色启用。账户安全性将在第4章中讨论。显而易见——但为了明确起见——复制需要第二个 Snowflake 账户。正如所述,账户可以位于任何支持的云提供商上。
可以说,Snowflake 的复制功能仍在不断完善中。保护数据的核心组件已经到位,尽管目前仅限于跨云提供商的数据库复制,这使得即时故障切换和恢复成为可能。预计在 2022 年上半年发布公共预览版本时,账户复制功能也将推出,计划支持对象级复制。数据库复制非常重要。微分区的不可变性质使数据共享成为可能,并与元数据同步。然而,还有其他因素需要考虑,例如将基础设施重新指向故障切换站点,并在服务恢复时无缝切换回去。这时,客户端重定向发挥了重要作用。
数据库复制与共享之间有一个根本的区别。共享对象的数据在消费方账户中实时可用。复制到另一个账户的数据库中的数据必须先刷新,且可能需要超过 20 秒才能出现在消费方账户中,因为无服务器计算操作需要完成。您的情况可能会有所不同,必须进行测试,以确保复制操作在可接受的时间内完成。
注意:复制的数据库可以进行本地或远程账户之间的复制,跨云提供商和区域也可行。
一些限制适用。当对象标签被部署时,复制操作会失败,且目标账户版本低于企业版。此外,必须在数据库中包含要复制的对象标签。包含外部表的数据库无法复制。外部引用的对象不会被复制,因此复制操作失败;从导入的共享创建的数据库也是如此。许多对象类型无法复制,包括用户、仓库、角色、资源监视器和网络策略。消息很明确:测试,测试,再测试。
注意:复制的数据库不会继承角色,角色必须重新创建。
在识别了复制数据库的几个限制后,很明显在为目标账户配置接收复制的数据库之前需要进行一些前置活动,并且在复制后需要执行一些数据库导入操作。然而,Snowflake 的复制功能正在不断改进,预计在未来的版本中,编码工作将减少。
无论选择哪个云提供商和区域,账户之间的复制都是可能的,但需要遵循文档中列出的限制。注意,所有次级副本都是只读的,直到其中一个副本被设为主副本。此后,主副本与所有其他副本一起变为可读写,而原始副本则回归只读模式。
相同云提供商和区域(Same Cloud Provider and Region)
在这种情况下,由于提供者和消费者账户依赖于相同的底层高可用性(HA)基础设施,因此数据保护方面存在一定的限制。然而,确实存在一些有效的场景,组织可能希望采用这种方式。例如,当合并或收购导致两个独立账户需要整合到同一组织下时,安全策略可能有所不同,或者账户支持不同的业务用例。在这些场景中,可以看到将部分数据整合到单一账户中是非常有益的,同时仍能独立保留各自的安全策略。共享(Shares)也可以在两个账户之间无缝交换数据集,且不产生额外成本,因为底层存储被重用,仅复制元数据。
相同云提供商和不同区域(Same Cloud Provider and Different Region)
在单一主区域发生故障时,复制的次级区域可以被激活为主区域,从而恢复服务。如果出现不太可能发生的情况,即 CSP(云服务提供商)或 Snowflake 遭遇两个或更多可用区(Availability Zone)故障,并且这两个账户都受到影响,则可能无法进行故障切换。尽管如此,这种事件的概率非常小。
对于相同云提供商、不同区域的情况,由于底层存储无法通过元数据共享,因此两个账户都将产生存储费用。两个账户必须各自实例化微分区。
不同云提供商和不同区域(Different Cloud Providers and Different Regions)
在单一主区域发生故障时,复制的次级区域可以被激活为主区域,从而恢复服务。如果 CSP 遭遇两个或更多的并发故障,使得 Snowflake 无法恢复,这种极端的情况被认为几乎不可能发生。
对于不同云提供商、不同区域的情况,由于底层存储无法通过元数据共享,因此两个账户都将产生存储费用。两个账户必须各自实例化微分区。此外,当数据在云提供商之间移动时,还会产生出口费用,当进行数据刷新时,这些费用很快会累积。
存储总结(Storage Summary)
遗憾的是,Snowflake 的文档在描述共享、克隆、复制以及可用选项时并不非常清晰。本节旨在总结可用的选项。表 3-1 提供了一个简要的总结。
| 存储选项 | 方法 | 存储费用 | 弹性 |
|---|---|---|---|
| 共享(Share) | 相同 CSP,相同区域 | 无,仅复制元数据 | 相同 CSP,高可用性,单一区域,实时 |
| 共享(Share) | 相同 CSP,不同区域 | 每个账户,每个区域产生存储费用 | 相同 CSP,高可用性,多区域 |
| 共享(Share) | 不同 CSP | 每个账户,每个区域产生存储费用 | 不同 CSP,高可用性,多区域 |
| 克隆数据库(Clone Database) | 相同账户 | 无,仅复制元数据(初始) | 相同 CSP,高可用性,单一区域 |
| 克隆数据库(Clone Database) | 相同 CSP,不同区域 | 不可用 | 不可用 |
| 克隆数据库(Clone Database) | 不同 CSP | 不可用 | 不可用 |
| 复制数据库(Replicated Database) | 相同 CSP,相同区域 | 无,仅复制元数据 | 相同 CSP,高可用性,单一区域,刷新 |
| 复制数据库(Replicated Database) | 相同 CSP,不同区域 | 每个账户,每个区域产生存储费用 | 相同 CSP,高可用性,多区域,刷新 |
| 复制数据库(Replicated Database) | 不同 CSP | 每个账户,每个区域产生存储费用 | 不同 CSP,高可用性,多区域,刷新 |
无服务器计算(Serverless Compute)
某些 Snowflake 功能不需要虚拟仓库,而是使用 Snowflake 提供并管理的计算资源。自然地,这些“幕后”功能仍然是有费用的,并会计入您的账户。
那么,哪些服务使用无服务器计算呢?这个列表还在增长,但目前包括了 Snowpipe、自动聚类、搜索优化服务、外部表元数据刷新、物化视图维护、数据库复制、故障切换和故障恢复,以及最近不再需要配置专用仓库的任务。
我们稍后将深入探讨其中一些功能。我已经提到了其他功能的自动维护。本节提醒您注意账单上单独列出的项目。欲了解更多解释,请参阅 Snowflake文档。
数据保护(Data Protection)
本节讨论了 Snowflake 可用的功能来保护我们的数据,重点是物理数据恢复。回顾一下,CSP 的高可用性(HA)如何为 99.999999999% 的持久性和 99.99% 的可用性提供信心。Snowflake 依赖于已发布的 CSP 高可用性能力来支持其产品功能。
时间旅行(Time Travel)
从微分区的管理讨论中,我们了解到其不可变的特性使得 Snowflake 具备了几项强大的内建功能。**时间旅行(Time Travel)**功能允许你将对象恢复到某个时间点,执行查询,或克隆数据。需要注意的是,标准版的最大时间限制为1天,而较高版本的最大时间限制可达90天。此外,时间旅行功能不能在账户级别禁用,但可以在数据库、模式(schemas)和表级别禁用。
**提示:**建议在使用 ACCOUNTADMIN 角色时,将 DATA_RETENTION_TIME_IN_DAYS 设置为 90 天。
假设设置了适当的保留期,Snowflake 管理员可以查询已更新或已删除的数据,并在保留期内的任何时间点恢复数据;还可以使用特定时间戳、相对时间戳偏移量或 SQL 查询 ID 创建数据库、模式和表的克隆。
启用时间旅行通常会产生 10% 到 15% 的存储开销,但由于存储成本较低,带来的好处远大于成本。如果你曾经等待数小时来恢复数据库的备份,那么这个功能将是你所需要的。由于微分区的不可变特性,恢复或克隆通常能在不到一分钟内完成,无论受影响的数据量有多大。当数据被恢复到较早的时间戳时,我们通常可以看到它带来的强大优势。我们都曾在生产系统中遇到过错误,比如在发布过程中不小心删除了对象、截断了表,或错误更新了数据。时间旅行功能为我们提供了一个快速恢复选项。无需请求数据库管理员恢复备份,我们有能力自助恢复,并通过不可变的 1 年查询历史来查找需要恢复的时间点或 SQL 语句。
不过,需要注意以下几点:
- 引用的对象必须在可用的保留期内。
- 恢复表和模式只支持在当前模式或数据库中操作,即使指定了完全限定的对象名。
- 执行
UNDROP命令的用户必须拥有该表的所有权权限,该权限需要在所使用的角色中进行授予。 - 用户还必须拥有目标模式的
CREATE权限。
需要注意的是,临时表和瞬态表的时间旅行最大保留期为 1 天,无论 Snowflake 版本如何。时间旅行功能不支持物化视图(materialized views)或外部表(external tables),因为物化视图的微分区是由现有表数据构建的,对于外部表,其存储不由 Snowflake 管理,仅由 Snowflake 引用。
更改账户或单个对象的保留期会更改所有未显式设置保留期的低级对象的保留期。如果在账户级别更改保留期,则所有没有显式保留期的数据库、模式和表将自动继承新的保留期。默认情况下,保留期为 1 天,并在初始配置时为所有账户启用。
提示: 强烈建议在创建数据库时将时间旅行功能设置为 90 天。
如果启用了时间旅行的表被删除,并且创建了一个具有相同名称的新表,则在执行 UNDROP 表命令时会失败。为了恢复先前版本的对象,必须重命名现有对象。
如果执行上下文设置正确,你可以通过执行以下命令查看表的版本历史:
SHOW TABLES HISTORY LIKE 'table_name' IN database.schema;
时间旅行功能应当被用于在发生数据加载错误时快速恢复服务,受影响的对象或数据库被恢复到数据加载前的时间点,然后小心地向前滚动数据,直到恢复正常服务。无需再等待数据库管理员恢复备份或花费数小时回滚事务。
故障保护(Fail-safe)
故障保护是一个数据恢复服务,提供了一个额外的 7 天保留期,由 Snowflake 独立管理,无法配置。它代表了存储生命周期的最终阶段。当对象过期出时间旅行保留期后,底层微分区不会立即释放并返回到云提供商的存储池,而是由 Snowflake 保留这些微分区——并推断保留的元数据——并且可以进行恢复,尽管这可能需要几个小时才能完成。
如果时间旅行保留期减少,超出该期限的对象会被移到故障保护服务中,并不再直接可访问。移动到故障保护中的对象在拥有账户内无法直接访问。要访问这些对象,必须通过向 Snowflake 提交支持工单。根据 Snowflake 文档,“故障保护并不是在时间旅行保留期结束后访问历史数据的手段,而是用于在极端操作故障导致数据丢失或损坏时恢复数据。”
需要注意的是,瞬态表、临时表和外部表没有故障保护服务期。故障保护还会对存储服务收取费用,费用是针对存储在 7 天保留期内的对象所消耗的存储空间。
备份策略(Backup Strategy)
考虑到 Snowflake 提供的数据保护选项,我们或许会问,备份策略是否仍然相关。这个问题没有简单的答案,因为涉及到多个主题,比如“被遗忘的权利”(right to be forgotten)。如果在 90 天的时间旅行保留期和 7 天的故障保护期之外发生了错误,误删除了某个人的详细信息,是否应该在删除个人数据之前,将所有受影响的对象做硬备份到离线存储中?组织的政策是什么,我们如何将政策转化为流程和操作程序?不幸的是,这些问题比答案更多,取决于你所在组织的 Snowflake 认知、理解和成熟度,旨在促使思考。
灾难恢复(Disaster Recovery, DR)
在讨论完数据保护后,我们转向灾难恢复(DR)的主题,这在我们之前的存储总结部分也有提到。考虑到我们的组织可能需要遵守外部的监管要求,而且一些业务同事可能未能完全理解 Snowflake 的固有强大功能,我们可能会被要求实施完整的灾难恢复政策,并配套相应的流程和程序。
我们的首要行动应该是告知并教育同事,Snowflake 与云服务提供商(CSP)提供的服务在本质上有显著不同,其内建的保护措施和工具也不同。通过初步的“思想和心智”教育活动、定期更新的内容和反复的讲解,我们可能会发现,Snowflake 内置的功能已能满足许多灾难恢复需求,从而减少我们的工作量。然而,我也认识到这需要时间,所以将以下信息作为制定你们灾难恢复策略的起点。
我们必须清楚地阐述每个环境,维护网络拓扑图、操作手册和灾难恢复运行手册(DR runbook)。这些文档应定期审查和批准,并以易于访问的形式存储。我们的组织也可能有一个集中的帮助台和工单系统,在服务中断期间遵循特定的操作流程。此时,我们的服务级别协议(SLA)文档规定了响应级别和时间线。我们还必须维护技术文档,确保支持人员可以访问有关我们系统各个方面的最新详细信息。对于经验丰富的开发人员来说,这些要求应该不会感到陌生。
业务连续性(Business Continuity)
我们的数据被安全存储在 Snowflake 中,并且在适当配置的情况下,可以通过时间旅行(Time Travel)功能随时访问过去 90 天内的任何数据。根据我们的数据复制策略,我们可以确保数据的可用性。然而,当我们深入探讨共享(shares)、克隆(clones)和复制(replication)的具体细节时,我们发现一些对象类型在处理上存在限制。这些限制需要根据具体情况逐一调查,并以 Snowflake 文档为首要参考,了解复制功能的不断发展。
Snowflake 无法考虑到所有可能的场景,每个组织的业务连续性要求和策略都会涉及一定的手动操作。必须说,Snowflake 中的故障转移(failover)和故障恢复(failback)比大多数其他平台要简单,但仍然需要一些工作。
你可能会找到现有或遗留的文档,帮助识别需要保护的关键基础设施,以确保服务的连续性。组织通常会有一个中央风险登记表,记录已知的薄弱环节。这些登记表应与应用程序、接口、服务和工具相对应。同样,你的组织可能拥有一个系统目录,其中包含应用程序所有者和支持小组的联系信息。对于那些更加前瞻性的组织和那些受到外部监管要求的组织,可能已经实现了从数据摄取到数据消费的端到端系统映射。这些资源反映了组织的成熟度,并为制定稳健的业务连续性计划提供了支持。
提示: 定期测试你的故障转移和故障恢复方案,通过克隆生产环境、进行复制,然后将克隆切换到另一个账户。尽可能使用自动化测试。
Snowflake 服务状态(Snowflake Service Status)
首要检查应当是你的 CSP 和所在位置的服务是否正常运行,参见 status.snowflake.com。如果服务受到影响,故障转移是由客户控制的手动操作,通过元数据更新实现,因此非常迅速。
故障转移和故障恢复(Failover and Failback)
根据你的复制数据库中包含的对象类型,可能需要运行额外的清理脚本。然而,我们希望所有清理工作已经由支持团队进行记录和文档化,以免出现意外问题。
我们还假设通过角色实现的安全模型已经应用于灾难恢复复制的数据库,并且所有权限与主站点一致。令人惊讶的是,很多情况下,人们假设权限会跟随复制对象进行变更,这在许多发布手册中常常被忽视。
自然,客户端工具需要重新指向,这在后续会单独讨论。批量加载、Snowpipe 和其他自定义加载机制也需要考虑,以确保在故障转移后无缝运行,其中某些数据流可能需要重新加载,其他则应避免重复执行。需要注意的是,某些 CSP 存储基础设施(如 AWS S3)允许独立复制,这可能简化故障转移和故障恢复的过程。
提示: 就像故障转移需要仔细考虑和规划一样,故障恢复也同样重要。
我们的故障转移和故障恢复还必须考虑 Snowflake 之外的 CSP 特定要求,例如,这些要求可能包括存储和 API 集成、Lambda、S3 和 SQS 配置等。
客户端重定向(Client Redirect)
客户端重定向利用 Snowflake 组织对访问 Snowflake 帐户的 URL 的增强功能。为每个帐户创建一个连接对象,其中只有一个指向主帐户。在发生故障转移时,连接对象会被更改为指向新的主帐户,从而在幕后更新 URL。更新 CNAME 记录(DNS 记录的一种类型)后,通常需要 30 到 60 秒,所有通过 URL 进行的新访问将指向新的主站点。
注意: 故障转移和客户端重定向是两个独立的操作。
扩展 Snowflake 能力
本节描述了 Snowflake 与云服务之间的一些交互,这些交互对于实现 Snowflake 数据云至关重要。更多功能将在后续章节中探讨。对于基于 AWS 的 Snowflake 帐户,S3 存储支撑着我们所有的数据库对象;因此,我们必须能够从 Snowflake 访问 S3 存储桶。我们还需要一种方式与 Snowflake 之外的云存储进行交互,因为我们的数据源通常以批量格式的平面文件提供。每个组织在某个时刻都会将数据传输解决为最低公分母的平面文件批量传输,期望之后再进行重构。我们从将平面文件作为数据传输的最低标准开始,将数据从各个数据孤岛迁移到 Snowflake。
现在不深入技术细节,但我必须引入一个新的组件——CSP 帐户,因为我们依赖的服务可在此访问。在我们的案例中是一个 AWS 帐户,可以在 aws.amazon.com/free 上创建。
为什么我们需要创建一个 AWS 帐户? 简单来说,为了访问您选择的云提供商开发和支持的大量功能,这些功能超出了 Snowflake 核心能力的范围。虽然 Snowflake 在数据处理方面提供了强大的功能,并且这些能力还在不断扩展,但有些功能永远不应该完全集成,例如 Secrets Manager;而有些功能则自然适合 Snowflake,例如 Lambdas、文档解析器和 S3 存储桶。
图 3-13 显示了 Snowflake 在两个位置引用的 S3 存储。请记住,我们的 Snowflake 帐户是一个虚拟私有客户端(VPC),而我们的 AWS 帐户也是一个 VPC,这两个不同的容器在相同(在此情况下,但也可以是不同)的云区域中共存。但请注意,Snowflake 可以引用这两个 S3 存储桶。那么,如何实现呢?
Snowflake 账户的边界允许我们访问无限的存储。我们只需声明并引用我们的弹性云资源,根据需要进行扩展。这些内部存储仅能在 Snowflake 的边界内引用,至少在写本书时是这样。不过,应该注意,未来的新功能可能会使这些内部存储在其他地方可访问。
在我们的 AWS 账户中,我们还可以创建 S3 存储,在其中我们可以从桌面机器上传文件,或者利用 AWS 提供的功能,自动从其他 S3 存储桶复制文件。我们也可以使用多种工具通过编程方式上传文件。
注意:AWS 账户中的 S3 存储桶中的未受保护文件可以从公共互联网查看,因此在添加文件之前,请确保已应用并测试适当的安全策略。
Snowflake 提供了一些命令,使得外部存储可见并可访问,这些命令被称为存储集成(文档链接)。这些命令需要在 Snowflake 和 AWS 管理控制台中进行配置,以建立信任关系。然后,我们可以将文件上传到 S3 存储桶,并使用 SQL 访问它们。这个主题将在第 10 章涉及到的非结构化文档支持中进一步讨论。
不仅如此,我们还可以通过使用 Snowflake 内建的功能 Snowpipe 来自动摄取数据,当文件落入我们的外部存储时,Snowpipe 会自动处理数据加载(文档链接)。图 3-14 已扩展,以包含一个新的 AWS 服务——简单队列服务(SQS)(SQS 文档链接),当文件准备好被处理时,SQS 会通知 Snowpipe。Snowpipe 在第 8 章中进一步讨论。
总结
本章介绍了 Snowflake 作为软件即服务(SaaS)如何在 CSP 区域中集中部署,并阐述了 Snowflake 账户是如何进行配置的。讨论还深入探讨了 Snowflake 的不同版本,特别指出了我们将在后续章节中调查的功能,并解答了为何我们需要与 AWS 账户进行集成的问题。
本章还探讨了云存储,分析了不同类型的存储阶段,了解它们的差异和用途,以及 Snowflake 如何通过微分区(micro-partitioning)来实现存储,因为微分区是 Snowflake 数据云核心功能的基础。
展望未来,随着未知的数据类型和新型媒体形式的到来,我们已经理解了如何应对未来的数据需求。现在,你可以开始将“是”作为你的首选回答,并通过知识和工具开发来访问数据,而不是因为答案超出了你的技能、知识、专业领域和舒适区而立即说“不”。
本讨论带你了解了访问数据孤岛的一些复杂性,指出了一些关键的依赖关系和挑战,其中安全态势是一个不容忽视的部分。
在为探索数据孤岛做好准备后,我们已经建立了正确的心态,接下来让我们打开通往账户安全章节的大门。