DoubleCloud 即将停止运营。使用限时免费迁移服务迁移到 ClickHouse。立即联系我们 ->->

博客 / 工程

ClickHouse 与 Snowflake 用于实时分析 - 对比和迁移

author avatar
ClickHouse 团队
2023 年 9 月 6 日

clickhouse_vs_snowflake_simple.png

摘要

本篇 ClickHouse 与 Snowflake 博客系列文章共两部分,可独立阅读。内容如下。

  • 对比和迁移 - 本文重点介绍 ClickHouse 和 Snowflake 之间的架构异同,并回顾了 ClickHouse Cloud 特别适用于实时分析用例的功能。对于有兴趣将工作负载从 Snowflake 迁移到 ClickHouse 的用户,我们将探讨数据集的差异以及迁移数据的方法。

  • 基准测试和成本分析 - 本系列的另一篇文章对一组用于支持提议应用程序的实时分析查询进行了基准测试。这些查询在两种系统中都进行了评估,使用各种优化方法,并直接比较了成本。我们的结果表明,ClickHouse Cloud 在我们的基准测试中,在成本和性能方面均优于 Snowflake。

    • ClickHouse Cloud 在生产环境中比 Snowflake 经济高效 3-5 倍。
    • 与 Snowflake 相比,ClickHouse Cloud 的查询速度快两倍以上。
    • ClickHouse Cloud 的数据压缩率比 Snowflake 高 38%。

介绍

Snowflake 是一个云数据仓库,主要专注于将传统的本地数据仓库工作负载迁移到云端。它针对大规模执行长时间运行的报表进行了优化。随着数据集迁移到云端,数据所有者开始思考如何从这些数据中提取更多价值,包括使用这些数据集为内部和外部用例的实时应用程序提供支持。当这种情况发生时,他们意识到他们需要一个针对实时分析进行了优化的数据库,例如 ClickHouse。

在整个评估过程中,我们力求公平,并承认 Snowflake 提供的一些优秀功能,特别是对于数据仓库用例。虽然我们认为自己是 ClickHouse 专家,但我们不是 Snowflake 专家,我们欢迎 Snowflake 用户提供更多经验的贡献和改进。我们承认 Snowflake 也可用于许多其他用例,但这些用例不在本文讨论范围内。

ClickHouse 与 Snowflake

相似之处

Snowflake 是一个基于云的数据仓库平台,它为存储、处理和分析大量数据提供可扩展且高效的解决方案。与 ClickHouse 一样,Snowflake 并非基于现有技术构建,而是依赖于其自己的 SQL 查询引擎和自定义架构。

Snowflake 的架构被描述为 共享磁盘(我们更倾向于使用“共享存储”一词)的混合体,数据通过使用诸如 S3 之类的对象存储从所有计算节点(共享磁盘)访问,以及 无共享 架构,每个计算节点在本地存储整个数据集的一部分以响应查询。理论上,这 兼具两种模型的优点:共享磁盘架构的简单性和无共享架构的可扩展性。

这种设计从根本上依赖于对象存储作为主要的存储介质,对象存储在并发访问下几乎可以无限扩展,同时提供高弹性和可扩展的吞吐量保证。

snowflake_architecture.png 来源:https://docs.snowflake.com/en/user-guide/intro-key-concepts

相反,作为一款开源且云托管的产品,ClickHouse 可部署在共享磁盘和无共享架构中。后者是自管理部署的典型特征。虽然允许轻松扩展 CPU 和内存,但无共享配置带来了传统的数据管理挑战和数据复制开销,特别是在成员变更期间。

为此,ClickHouse Cloud 使用了一种与 Snowflake 相似的共享存储架构。数据存储在对象存储(单一副本)中,例如 S3 或 GCS,这提供了几乎无限的存储空间,并具有强大的冗余保证。每个节点都可以访问数据的这一个副本,以及用于缓存目的的本地 SSD。节点可以反过来进行扩展,以根据需要提供额外的 CPU 和内存资源。与 Snowflake 一样,S3 的可扩展性属性解决了共享磁盘架构的传统限制(磁盘 I/O 和网络瓶颈),通过确保集群中当前节点可用的 I/O 吞吐量在添加新节点时不会受到影响。

clickhouse_architecture.png

差异

除了底层存储格式和查询引擎之外,这些架构在一些细微方面有所不同。

  • Snowflake 中的计算资源通过 仓库 的概念提供。它们包含一定数量的节点,每个节点都具有一定的大小。虽然 Snowflake 没有公布其仓库的具体架构,但 人们普遍认为 每个节点包含 8 个 vCPU、16GiB 和 200GB 的本地存储(用于缓存)。节点数量取决于“T 恤尺码”,例如,XS 尺寸包含一个节点,S 尺寸包含 2 个节点,M 尺寸包含 4 个节点,L 尺寸包含 8 个节点,等等。这些仓库与数据无关,可用于查询驻留在对象存储中的任何数据库。当处于空闲状态并且没有受到查询负载的影响时,仓库将暂停 - 在接收到查询时恢复。虽然存储成本始终反映在计费中,但仓库仅在处于活动状态时才收费。
  • ClickHouse Cloud 使用了类似的具有本地缓存存储的节点原则。用户不是使用“T 恤尺码”,而是部署具有总计算量和可用内存的服务。这反过来根据查询负载透明地自动扩展(在定义的限制范围内) - 通过增加(或减少)每个节点的资源进行垂直扩展,或通过增加/减少节点总数进行水平扩展。ClickHouse Cloud 节点目前具有 1:4 的 CPU 与内存比率,而 Snowflake 的比率为 1:2。虽然更松散的耦合是可能的,但服务目前与数据耦合,与 Snowflake 仓库不同。如果处于空闲状态,节点也会暂停,如果受到查询,则会恢复。用户也可以根据需要手动调整服务大小。
  • ClickHouse Cloud 的查询缓存目前是节点特定的,与 Snowflake 不同,Snowflake 的查询缓存是在独立于仓库的服务层提供的。尽管如此,根据我们的基准测试,上述节点缓存的性能优于 Snowflake 的缓存。
  • Snowflake 和 ClickHouse Cloud 在扩展以提高查询并发性方面采取了不同的方法。Snowflake 通过一项名为 多集群仓库 的功能来解决这个问题。此功能允许用户向仓库添加集群。虽然这不会提高查询延迟,但它确实提供了额外的并行化并允许更高的查询并发性。ClickHouse 通过垂直或水平扩展,为服务添加更多内存和 CPU 来实现这一点。在本博文中,我们没有探讨这些服务扩展到更高并发性的能力,而是专注于延迟,但承认应该为完整比较完成这项工作。但是,我们预计 ClickHouse 将在任何并发测试中表现良好,Snowflake 明确限制了 仓库默认允许的并发查询数量为 8。相比之下,ClickHouse Cloud 允许每个节点执行多达 1000 个查询。
  • Snowflake 能够在数据集上切换计算大小,再加上仓库的快速恢复时间,使其成为临时查询的绝佳体验。对于数据仓库和数据湖用例,这比其他系统更具优势。

我们提供了有关功能和数据类型相似点和差异的附加列表,如下所示。

实时分析

根据我们的基准分析,ClickHouse 在以下领域优于 Snowflake,适用于实时分析应用程序

  • 查询延迟:即使对表应用聚类以优化性能,Snowflake 查询的查询延迟也更高。在我们的测试中,Snowflake 需要超过两倍的计算量才能在查询中实现与 ClickHouse 相同的性能,这些查询应用了过滤器,该过滤器是 Snowflake 聚类键或 ClickHouse 主键的一部分。虽然 Snowflake 的 持久查询缓存 弥补了一些这些延迟挑战,但在过滤器条件更多样化的情况下,这是无效的。当表发生变化时,缓存条目将失效,这会进一步影响查询缓存的有效性。虽然在我们的应用程序基准测试中并非如此,但实际部署将需要插入新的、更新的数据。请注意,ClickHouse 的查询缓存是节点特定的,而不是 事务一致的,使其 更适合实时分析。用户还可以通过在 每个查询的基础上 控制其使用,对其 精确大小 进行控制,以及是否 缓存查询(对持续时间或所需执行次数的限制)以及它是否仅 被动使用 来实现对其实用的精细控制。
  • 成本更低:Snowflake 仓库可以配置为在一段时间查询不活动后暂停。暂停后,不会产生费用。实际上,此不活动检查 只能降低到 60 秒。仓库将在收到查询后几秒钟内自动恢复。由于 Snowflake 仅在仓库使用时才收取资源费用,因此此行为适合于经常处于闲置状态的工作负载,例如临时查询。

    但是,许多实时分析工作负载需要持续的实时数据摄取和频繁查询,而这些查询无法从闲置中受益(例如面向客户的仪表板)。这意味着仓库通常必须处于完全活动状态并产生费用。这抵消了闲置的成本效益以及与 Snowflake 能够比其他替代方案更快地恢复到响应状态相关的任何性能优势。当结合 ClickHouse Cloud 的更低的活动状态每秒成本时,这种活动状态需求会导致 ClickHouse Cloud 为这些类型的工作负载提供明显更低的总成本。
  • 功能价格可预测:物化视图和聚类(相当于 ClickHouse 的 ORDER BY)等功能是实现实时分析用例最高性能水平所必需的。这些功能在 Snowflake 中会产生额外的费用,不仅需要更高的层级,这会将每积分成本提高 1.5 倍,还会产生不可预测的后台成本。例如,物化视图会产生后台维护成本,聚类也是如此,这在使用前很难预测。相比之下,这些功能在 ClickHouse Cloud 中不会产生额外费用,除了插入时额外的 CPU 和内存使用量,通常在高插入工作负载用例之外可以忽略不计。我们在基准测试中观察到,这些差异以及更低的查询延迟和更高的压缩率导致 ClickHouse 的成本明显更低。

ClickHouse 用户也对 ClickHouse 提供的广泛的实时分析功能支持表示赞赏,例如

  • 广泛的专用分析函数缩短并简化了查询语法,例如 聚合组合器数组函数,从而提高了复杂查询的性能和可读性。
  • 旨在使分析查询更容易的 SQL 查询语法,例如 ClickHouse 不像 Snowflake 那样强制执行 SELECT 中的别名。
  • 更具体的数据类型,例如对枚举和具有明确精度的数值的支持。后者允许用户节省未压缩的内存。Snowflake 将较低精度的数值视为等效全精度类型的别名。
  • 与 Snowflake 中的 有限选择 相比,它具有优越的 文件和数据格式 支持,简化了分析数据的导入和导出。
  • 联合查询功能,支持对各种数据湖和数据存储进行临时查询,包括 S3、MySQL、PostgreSQL、MongoDB、Delta Lake 等。
  • 能够为列指定 自定义模式或编解码器 以实现更高的压缩率。此功能使我们能够在基准测试中优化压缩率。
  • 辅助索引和投影。ClickHouse 支持 辅助索引,包括用于文本匹配的 倒排索引,以及 投影,以允许用户针对特定查询进行优化。虽然投影在概念上类似于 Snowflake 物化视图,但它们不受 相同限制 的约束,所有聚合函数都支持。投影的使用也不会影响定价(这会导致 Snowflake 的层级发生变化,使费用增加 1.5 倍),除了与增加存储相关的开销。我们在基准分析中展示了这些功能的有效性。
  • 对物化视图的支持。这些与 Snowflake 物化视图不同(与 ClickHouse 投影更可比),因为它们是仅对插入的数据执行的触发器。ClickHouse 物化视图 与投影相比具有明显的优势,特别是
    • 物化视图的结果可以存储在另一个表中。这可以是插入数据的子集或聚合,并且可以明显更小。与投影(或 Snowflake 中的物化视图)不同,不需要保留原始插入数据,这可能节省了大量的存储空间。如果用户只需要存储汇总数据,物化视图可以提供显著的存储和性能增益。
    • 支持联接和 WHERE 过滤器,与投影不同。
    • 物化视图可以链接,即当插入数据时可以执行多个视图,每个视图都生成自己的汇总数据形式。

集群与排序

ClickHouse 和 Snowflake 都是列式数据库。由于更有效地利用了 CPU 缓存和 SIMD 指令,这种数据方向对于分析工作负载优于行式存储和执行。此外,它确保排序列可以更有效地压缩,因为常见的压缩算法可以利用重复的值。虽然它们在数据存储方面采用了不同的方法,但这两个系统都需要排序和索引以获得最佳读取性能。这创建了一些类似的概念,用户可以在对比和迁移系统之间的数据时利用这些概念,即使实现方式不同。

ClickHouse 的核心是使用稀疏索引和排序数据。在创建表时,用户会指定包含列元组的 ORDER BY 子句。这明确地控制了数据的排序方式。通常,这些 列应根据频繁查询进行选择,并按基数增加的顺序排列。 除了控制磁盘上数据的顺序之外,ORDER BY 还默认配置了关联的稀疏主索引。这可以通过 PRIMARY KEY 子句覆盖。请注意,ORDER BY 必须包含 PRIMARY KEY 作为前缀,因为后者假定数据已排序(请参阅 此处,了解这些差异可能存在的位置)。此稀疏索引依赖于磁盘上排序的数据,并且对于 ClickHouse 中的快速查询执行至关重要,因为它允许有效地扫描数据,如果数据与谓词不匹配,则跳过数据。

Snowflake 虽然在磁盘上的 存储结构(使用微分区)方面有所不同,但通过 聚类 提供了类似的概念。此子句允许用户指定一组控制如何将数据分配到微分区的列,目的是确保具有这些列相同值的 ​​数据位于同一个位置。通过有效地控制磁盘上的数据顺序,聚类提供了类似的性能和压缩增益,与 ClickHouse 的 ORDER BY 相比。

尽管它们在概念上相似,但它们的实现方式存在一些差异,这些差异会影响后续使用

  • ClickHouse 在插入时根据 ORDER BY 对数据进行排序,并在数据写入磁盘时构建稀疏索引。在写入时没有额外成本和可忽略不计的开销,即使对于快速变化的表,也可以进行适当的优化。
  • Snowflake 异步执行聚类,在后台消耗积分以将数据分配到正确的分区,此过程称为 自动聚类。在此过程中将消耗的积分无法轻松预测。虽然适合于使用多 TB 数据频繁查询的表,但 Snowflake 不建议对快速变化的表进行聚类。用于的列的基数将严重影响聚类的开销和消耗的积分 - Snowflake 建议使用表达式(例如 to_date)来减轻这种影响。对用户而言,最重要的一个方面是聚类发生的时机不确定,因此在应用于表时,其益处不会立即可用。此过程是增量的,随着时间的推移,聚类会逐渐改善,然后稳定下来(假设没有添加更多数据)。
  • Snowflake 允许数据在 可能很高的成本 下重新聚类。由于采用了微分区方法,这在 Snowflake 中是可能的,而在 ClickHouse 中,则需要完全重写数据。

尽管存在上述差异,但这些特性对于分析工作负载至关重要。分析工作负载需要使用 `GROUP BY` 操作对特定列进行选择、过滤和排序,以支持构建带有钻取功能的图表。在这两种情况下,将各自子句中使用的列映射到工作负载都很重要。很大比例的查询应该从聚类/排序键中受益,大多数查询应该命中这些列。

在选择 `ORDER BY` 和 `CLUSTER BY` 子句的列时,ClickHouse 和 Snowflake 提供了类似的建议。

  • 使用在选择性过滤器中积极使用的列。在 `GROUP BY` 操作中使用的列也有助于节省内存。
  • 尝试使用具有足够基数的列,以确保有效地修剪表,例如,包含硬币抛掷结果的列通常会修剪 < 50% 的表。
  • 在定义多列时,用户应该尝试确保列按从最低到最高的基数排序。通常,在两种情况下,这都会使对后续列的过滤更加高效。虽然 Snowflake 的详细信息不可用,但我们预计这与 ClickHouse 中为什么这很重要 相似。

注意:虽然上述建议一致,但 Snowflake 建议避免在聚类键中使用高基数列。但这不会影响 ClickHouse,例如,`timestamp` 等列是 `ORDER BY` 子句的有效选择。

我们在后续基准测试中考虑了这些建议。

迁移数据

希望在 Snowflake 和 ClickHouse 之间迁移数据的用户可以使用对象存储(例如 S3)作为中间存储进行传输。此过程依赖于分别使用 Snowflake 和 ClickHouse 的 `COPY INTO` 和 `INSERT INTO SELECT` 命令。我们在下面概述了此过程。

migrating_clickhouse_snowflake.png

从 Snowflake 卸载

Snowflake 导出需要使用 外部阶段,如上图所示。这在概念上类似于 ClickHouse S3 表引擎,它通过逻辑地封装一组外部托管的文件,并允许在 SQL 语句中一致地引用它们。

我们建议在系统之间传输数据时使用 Parquet 作为中间格式,主要是因为它允许共享类型信息,保留精度,压缩良好,并且原生支持分析中常见的嵌套结构。用户也可以卸载到 `ndjson` 格式的 JSON 中 - ClickHouse 通过 JSONEachRow 支持这一点,但这通常要详细得多,并且在解压缩时更大。

在下面的示例中,我们卸载了 PyPi 数据集的 650 亿行。该模式和数据集起源于 公共 BigQuery 表,在 我们的基准测试 中进行了更详细的描述。 该数据集 包含使用 PiP 等工具下载的每个 Python 包的一行。选择此数据集是因为其规模(所有数据超过 5500 亿行),以及其模式和结构类似于实时分析用例中遇到的结构。

在下面的示例中,我们在 Snowflake 中创建一个 命名文件格式 来表示 Parquet 和所需的文件选项。然后,在声明外部阶段时使用它,该阶段将使用 `COPY INTO` 命令。这通过可以授予权限的 S3 存储桶提供了抽象。

请注意,Snowflake 提供了几种方法 来共享对 S3 存储桶的写入访问权限的凭据。虽然我们在声明阶段时直接使用了选项 3(使用密钥和机密来简化下面的示例),但在生产中建议使用 Snowflake 存储集成 方法以避免共享凭据。

CREATE FILE FORMAT my_parquet_format TYPE = parquet;

CREATE OR REPLACE STAGE my_ext_unload_stage 
URL='s3://datasets-documentation/pypi/sample/'
CREDENTIALS=(AWS_KEY_ID='<key>' AWS_SECRET_KEY='<secret>')
FILE_FORMAT = my_parquet_format;

-- apply pypi prefix to all files and specify a max size of 150mb
COPY INTO @my_ext_unload_stage/pypi from pypi max_file_size=157286400 header=true;

Snowflake 模式

CREATE TABLE PYPI (
   timestamp TIMESTAMP,
   country_code varchar,
   url varchar,
   project varchar,
   file OBJECT,
   installer OBJECT,
   python varchar,
   implementation OBJECT,
   distro VARIANT,
   system OBJECT,
   cpu varchar,
   openssl_version varchar,
   setuptools_version varchar,
   rustc_version varchar,
   tls_protocol varchar,
   tls_cipher varchar
) DATA_RETENTION_TIME_IN_DAYS = 0;

导出到 Parquet 后,它会生成 5.5TiB 的数据,最大文件大小为 150MiB。位于相同 AWS us-east-1 区域的 2X-LARGE 仓库大约需要 30 分钟。这里的 `header=true` 参数是获取列名所必需的。VARIANT 和 OBJECT 列也会默认 以 JSON 字符串的形式输出,迫使我们在将它们插入 ClickHouse 时进行强制转换。

导入 ClickHouse

一旦在中间对象存储中进行暂存,就可以使用 ClickHouse 函数(例如 s3 表函数)将数据插入表中,如下所示。

假设以下表目标模式

CREATE TABLE default.pypi
(
	`timestamp` DateTime64(6),
	`date` Date MATERIALIZED timestamp,
	`country_code` LowCardinality(String),
	`url` String,
	`project` String,
	`file` Tuple(filename String, project String, version String, type Enum8('bdist_wheel' = 0, 'sdist' = 1, 'bdist_egg' = 2, 'bdist_wininst' = 3, 'bdist_dumb' = 4, 'bdist_msi' = 5, 'bdist_rpm' = 6, 'bdist_dmg' = 7)),
	`installer` Tuple(name LowCardinality(String), version LowCardinality(String)),
	`python` LowCardinality(String),
	`implementation` Tuple(name LowCardinality(String), version LowCardinality(String)),
	`distro` Tuple(name LowCardinality(String), version LowCardinality(String), id LowCardinality(String), libc Tuple(lib Enum8('' = 0, 'glibc' = 1, 'libc' = 2), version LowCardinality(String))),
	`system` Tuple(name LowCardinality(String), release String),
	`cpu` LowCardinality(String),
	`openssl_version` LowCardinality(String),
	`setuptools_version` LowCardinality(String),
	`rustc_version` LowCardinality(String),
	`tls_protocol` Enum8('TLSv1.2' = 0, 'TLSv1.3' = 1),
	`tls_cipher` Enum8('ECDHE-RSA-AES128-GCM-SHA256' = 0, 'ECDHE-RSA-CHACHA20-POLY1305' = 1, 'ECDHE-RSA-AES128-SHA256' = 2, 'TLS_AES_256_GCM_SHA384' = 3, 'AES128-GCM-SHA256' = 4, 'TLS_AES_128_GCM_SHA256' = 5, 'ECDHE-RSA-AES256-GCM-SHA384' = 6, 'AES128-SHA' = 7, 'ECDHE-RSA-AES128-SHA' = 8)
)
ENGINE = MergeTree
ORDER BY (date, timestamp)

由于 Snowflake 将 `file` 等嵌套结构转换为 JSON 字符串,因此导入此数据需要我们在 ClickHouse 中的插入时使用 JSONExtract 函数 将这些结构转换为适当的元组,如下所示。

INSERT INTO pypi
SELECT
	TIMESTAMP,
	COUNTRY_CODE,
	URL,
	PROJECT,
	JSONExtract(ifNull(FILE, '{}'), 'Tuple(filename String, project String, version String, type Enum8(\'bdist_wheel\' = 0, \'sdist\' = 1, \'bdist_egg\' = 2, \'bdist_wininst\' = 3, \'bdist_dumb\' = 4, \'bdist_msi\' = 5, \'bdist_rpm\' = 6, \'bdist_dmg\' = 7))') AS file,
	JSONExtract(ifNull(INSTALLER, '{}'), 'Tuple(name LowCardinality(String), version LowCardinality(String))') AS installer,
	PYTHON,
	JSONExtract(ifNull(IMPLEMENTATION, '{}'), 'Tuple(name LowCardinality(String), version LowCardinality(String))') AS implementation,
	JSONExtract(ifNull(DISTRO, '{}'), 'Tuple(name LowCardinality(String), version LowCardinality(String), id LowCardinality(String), libc Tuple(lib Enum8(\'\' = 0, \'glibc\' = 1, \'libc\' = 2), version LowCardinality(String)))') AS distro,
	JSONExtract(ifNull(SYSTEM, '{}'), 'Tuple(name LowCardinality(String), release String)') AS system,
	CPU,
	OPENSSL_VERSION,
	SETUPTOOLS_VERSION,
	RUSTC_VERSION,
	TLS_PROTOCOL,
	TLS_CIPHER
FROM s3('https://datasets-documentation.s3.eu-west-3.amazonaws.com/pypi/2023/pypi*.parquet')
SETTINGS input_format_null_as_default = 1, input_format_parquet_case_insensitive_column_matching = 1

我们依赖于设置 `input_format_null_as_default=1``input_format_parquet_case_insensitive_column_matching=1` 以确保如果为空,则将列插入为默认值,并且源数据和目标表之间的列匹配不区分大小写。

如果使用 AzureGoogle Cloud,可以创建类似的过程。请注意,ClickHouse 中存在专门的函数 [1][2] 用于从这些对象存储中导入数据。

结论

在这篇文章中,我们对比了 Snowflake 和 ClickHouse 在实时分析用例中的应用,考察了这两个系统之间的异同。我们已经确定了对该用例有益的 ClickHouse 特性,并探讨了用户如何从 Snowflake 迁移工作负载。在 本系列的下一篇文章 中,我们将介绍一个示例实时分析应用程序,识别压缩和插入性能方面的差异,并对代表性查询进行基准测试。最后将进行成本分析,其中我们将展示使用 ClickHouse Cloud 可能节省的成本。


附录

希望从 Snowflake 迁移实时分析工作负载到 ClickHouse 的用户可能需要了解几个关键概念。下面,我们提供有关核心聚类和排序中的数据类型和等效性的更多信息。这些信息补充了之前关于数据传输的高级方法的部分。

数据类型

数值型

在 ClickHouse 和 Snowflake 之间移动数据的用户会立即注意到 ClickHouse 在声明数字方面提供了更细粒度的精度。例如,Snowflake 为数字提供了 `Number` 类型。这要求用户指定精度(总位数)和比例(小数点右边的位数),总共最多 38 位。整数声明与 `Number` 同义,并且只定义固定的精度和比例,其中范围相同。这种方便性是可能的,因为修改精度(比例对于整数为 0)不会影响 Snowflake 中磁盘上数据的尺寸 - 最小的必需字节是在微分区级别写入时用于数字范围的。然而,比例会影响存储空间,并通过压缩进行抵消。Float64 类型提供更广泛的值范围,但会损失精度。

将此与 ClickHouse 进行对比,ClickHouse 为浮点数和整数提供多种带符号和无符号精度。有了这些,ClickHouse 用户可以明确指定整数所需的精度,以优化存储和内存开销。与 Snowflake 的 Number 类型等效的 Decimal 类型也提供了两倍的精度和比例,达到 76 位。除了类似的 Float64 值之外,ClickHouse 还提供 Float32,用于精度不太重要且压缩至关重要的情况。

字符串型

ClickHouse 和 Snowflake 对字符串数据的存储采用了对比的方法。Snowflake 中的 VARCHAR 以 UTF-8 形式保存 Unicode 字符,允许用户指定最大长度。此长度对存储或性能没有影响,始终使用最少的字节数来存储字符串,而只是提供对下游工具有用的约束。其他类型,例如 Text 和 NChar,只是此类型的别名。相反,ClickHouse 使用 String 类型(无需指定长度)将所有 字符串数据存储为原始字节,将编码推迟到用户,并提供 查询时函数 用于不同的编码(有关动机,请参见 此处)。因此,ClickHouse String 在其实现上更类似于 Snowflake Binary 类型。SnowflakeClickHouse 都支持“排序规则”,允许用户覆盖字符串的排序和比较方式。

半结构化

Snowflake 和 ClickHouse 在对半结构化数据的丰富类型支持方面具有可比性,分别通过 VARIANT(实际上是超类型)JSON 类型 提供这种支持。这些类型允许“稍后确定模式”,其中基础数据类型由数据库在插入时识别。Snowflake 还支持 ARRAY 和 OBJECT 类型,但这些只是 VARIANT 类型的限制。

ClickHouse 还通过 Nested 类型支持命名元组和元组数组,允许用户明确映射嵌套结构。这允许在整个层次结构中应用编解码器和类型优化,这与 Snowflake 不同,Snowflake 要求用户对外部对象使用 OBJECT、VARIANT 和 ARRAY 类型,并且不允许 显式内部类型。这种内部类型也简化了对 ClickHouse 中嵌套数字的查询,这些查询不需要进行强制转换,并且可以在索引定义中使用。

在 ClickHouse 中,编解码器和优化类型也可以应用于子结构。这提供了额外的优势,即嵌套结构的压缩仍然非常出色,并且与扁平数据相当。相反,由于无法对子结构应用特定类型,因此 Snowflake 建议 扁平化数据以实现最佳压缩。Snowflake 还对这些数据类型 施加了尺寸限制

下面,我们将为从 Snowflake 迁移工作负载到 ClickHouse 的用户映射等效类型。

SnowflakeClickHouse注意
NUMBERDecimalClickHouse 支持的精度和比例是 Snowflake 的两倍 - 76 位 vs. 38 位。
FLOAT、FLOAT4、FLOAT8Float32、Float64Snowflake 中的所有浮点数都是 64 位。
VARCHARString
BINARYString
BOOLEANBool
DATEDateDate32Snowflake 中的 DATE 提供比 ClickHouse 更广泛的日期范围,例如,Date32 的最小值为 `1900-01-01`,Date 的最小值为 `1970-01-01`。ClickHouse 中的 Date 提供了更具成本效益的存储(2 个字节)。
TIME(N)没有直接的等效项,但可以用 DateTimeDateTime64(N) 表示。DateTime64 使用相同的精度概念。
TIMESTAMP - TIMESTAMP_LTZTIMESTAMP_NTZTIMESTAMP_TZDateTimeDateTime64DateTime 和 DateTime64 可以选择为列定义 TZ 参数。如果不存在,则使用服务器的时区。此外,还为客户端提供了 `--use_client_time_zone` 参数。
VARIANTJSON、元组、嵌套ClickHouse 中的 JSON 类型是实验性的。此类型在插入时推断列类型。元组、嵌套和数组也可以用作替代方案,用于显式构建类型结构。
对象元组、映射、JSON对象和映射都类似于 ClickHouse 中的 JSON 类型,其中键是字符串。ClickHouse 要求值为一致的强类型,而 Snowflake 使用 VARIANT。这意味着不同键的值可以是不同的类型。如果 ClickHouse 中需要此功能,请使用元组显式定义层次结构或依赖 JSON 类型。
数组数组嵌套Snowflake 中的数组对元素使用 VARIANT - 一种超级类型。相反,这些在 ClickHouse 中是强类型的。
地理点、环、多边形、多边形Snowflake 强制使用坐标系(WGS 84),而 ClickHouse 在查询时应用坐标系。
几何点、环、多边形、多边形

除了以上之外,ClickHouse 还提供
  • IP 特定类型 ipv4ipv6,可能比 Snowflake 更有效地存储数据。
  • FixedString - 允许使用固定长度的字节,这对哈希非常有用。
  • LowCardinality - 允许对任何类型进行字典编码。当基数预计小于 100k 时很有用。
  • Enum - 允许在 8 或 16 位范围内有效编码命名值。
  • UUID 用于高效存储 uuid。
  • 向量可以表示为 Float32 数组,并支持距离函数。

最后,ClickHouse 提供了独特的存储中间 聚合函数状态 的功能。此状态是特定于实现的,但允许存储聚合结果并稍后查询(使用相应的 合并函数)。通常,此功能通过物化视图使用,并且如以下所示,通过存储插入数据上的查询的增量结果,可以以最小的存储成本快速加速特定查询(更多详细信息 此处)。

联系我们 今天了解更多关于 ClickHouse Cloud 的实时分析。或者,开始使用 ClickHouse Cloud 并获得 300 美元的积分。

分享此文章

订阅我们的时事通讯

及时了解功能发布、产品路线图、支持和云服务!
正在加载表格...
关注我们
Twitter imageSlack imageGitHub image
Telegram imageMeetup imageRss image