【问题标题】:Would storing data in a wide format achieve better performance in Snowflake?以宽格式存储数据会在 Snowflake 中获得更好的性能吗?
【发布时间】:2022-09-28 19:36:24
【问题描述】:

我试图了解 Snowflake 在宽桌子方面的能力。

我有一张表格:

userId metricName value asOfDate
1 \'meanSessionTime\' 30 2022-01-04
1 \'meanSessionSpend\' 20 2022-01-04
2 \'meanSessionTime\' 34 2022-01-05
... ... ... ...

但是,对于我的分析,我通常将该表的大部分子集拉入 Python 并导出指标名称

userId asOfDate meanSessionTime meanSessionSpend ...
1 2022-01-04 30 20 ...
2 2022-01-05 43 12 ...
... ... ... ... ...

我正在考虑在 Snowflake 中生成这个 Pivot(通过 DBT,SQL 本身并不难),但我不确定这是好还是坏。

将数据保存为长格式有什么好的理由吗?有什么好的理由去广泛?

请注意,我不打算总是从宽表中使用SELECT * ,因此它可能是列式存储的一个很好的用例。

笔记:

这些是大表(数十亿或记录,数百个指标),所以我正在寻找一个意义检查,然后再烧掉几百美元的学分做一个实验。

  • 您能否提供有关指标总数的更多详细信息?
  • 此外,随着时间的推移,您是否可能不得不处理添加到数据模型中的新指标?指标是密集的还是稀疏的,有很多 NULL/默认值,您会存储 NULL/默认值行,还是在查询时估算它们?您期望的典型查询列计数有效负载是什么,因为您已经说过您并不总是选择查询中的每一列。有多少用户?同时更改给定用户的所有指标,或仅更改一小部分。
  • @Fieldy,我们有大约 600 个指标。它们很密集,并且每年都会添加新功能。历史数据未更新,因此可以将其视为仅附加数据集。可能会在任何时候选择 20-100 列。

标签: snowflake-cloud-data-platform


【解决方案1】:

感谢 cmets 中提供的其他详细信息,并为延迟响应表示歉意。一些想法。

我已经使用 Wide 和 Tall 表来表示 Snowflake 中的特征/指标存储。您还可以潜在地使用半结构化列来存储宽表示。或者,如果您的指标可以是不同的数据类型(例如数字和字符),则采用 Tall 格式,以将指标值存储在单个 VARIANT 列中。

使用约 600 个指标(列),您仍处于 Snowflakes 行宽的限制范围内,但表越宽,通常在编写针对它的查询或仅检索结果以进行进一步分析时,它的可用性/可管理性就越差。

由于键(例如 user-id、asOfDate)和 metricName 以及您在 tall 格式中可能需要的任何其他列的重复,宽格式通常会导致比 tall 格式更小的存储空间。在某些实现中,我已经看到 Tall 格式的存储空间增加了 3-5 倍,因此如果您转向 Wide 模型,您应该会看到一些存储空间节省。

在 Tall 表中,这可以通过clustering 表最小化,因此相同的键和/或度量列值被收集到相同的微分区中,从而有利于更好的压缩和访问。此外,正如我的 cmets/questions 中所提到的,如果某些指标是稀疏的,或者具有占主导地位的默认值分布,或者以显着不同的速率更改值,则迁移到稀疏高形式可以实现更高效的存储和处理。在宽格式中,如果 600 个度量值中只有一个值发生变化,那么在给定的一天,您仍然需要写入一条包含所有 599 个未更改值的新记录。而在 tall 表单中,您可以为具有更改值的指标编写一条记录。

在宽格式中,Snowflakes 列存储/访问应该有效地消除对查询中未包含的列的物理扫描,因此它们应该至少与高格式一样有效,并且列压缩技术可以有效地最小化物理存储。

假设您的数据没有按照分析模式的最佳顺序插入到 tall 表中,该表需要为 clustered 才能使用 CLUSTER BY 获得最佳性能。例如,如果您总是在用户 ID 的子集上进行过滤,则它应该在您的 CLUSTER BY 中具有优先权,但如果您主要针对所有用户 ID 或所有用户 ID 搜索列的子集,那么metricName 应该优先。集群有额外的服务成本,这可能成为使用 tall 格式的一个因素。

在 tall 格式中,具有明确定义的度量名称标准可以实现列选择的编程方法。例如column names as contracts 这使得将列组作为一个单元使用 WHERE 子句“选择”列组(例如,使用 LIKE)非常有效,并有效地对其应用操作。 IMO 这使得编写更简洁和可维护的 SQL 成为可能,而不必使用 Jinja 或 DBT 等模板工具。

通过将度量名称/值对分组和存储在 OBJECT 列中,而不是作为单独的列,可以在宽格式中实现类似的灵活性。可以使用OBJECT_AGG 将它们收集(透视)到一个对象。然后可以在对象上使用雪花半结构化功能。 Snowflake 隐式地对半结构化列进行分栏化,达到一个点/限制,但是对于 600 多列,您的一些数据将不会从中受益,这可能会影响性能。如果您知道哪些列最常用于过滤或在查询中返回,您可以混合使用这两种方法

我还使用 Snowflake UDF 有效地使用 Javascript 对 OBJECT 列执行常用的过滤、投影或转换操作,但请注意,您使用的是 Python,新的 Python UDF 功能可能是您更好的选择。当您将数据检索到 Python 以进行进一步分析时,您可以轻松地将 OBJECT 转换为 Python 中的 DICT 以进行进一步迭代。您还可以查看Snowpark for Python,它应该使您能够将进一步的分析和处理从 Python 推送到 Snowflake。

【讨论】:

    猜你喜欢
    • 2011-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-19
    • 2021-04-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多