【问题标题】:UPDATE millions of rows, or DELETE/INSERT?更新数百万行,还是删除/插入?
【发布时间】:2021-01-05 04:34:36
【问题描述】:

抱歉,描述太长了...但是我们开始...

我们有一个事实表,其中包含一些属性,您可能已将这些属性放入更“经典”数据仓库的维度中。 我希望该表中有数十亿行。

我们希望通过一些不会经常更改但仍会不时更改的清理/分组来丰富这些属性。

我们正在考虑将这个初始事实表保留为我们从不更新或删除的“主”表,并为其创建一个“扩展事实”表副本,我们只需在其中添加新的派生属性。

生成这些扩展属性值的过程需要映射到某个查找表的堡垒,我们从中得到每一行的几种可能性,然后选择最佳的一种(每个初始行一个)。 这可能是处理器密集型的。

问题(终于!):

想象一下我的查找表被修改了,我想重新评估我的初始事实表的一个子集的扩展属性。

我最终会在目标扩展事实表中修改几百万行。

实现此更新的最佳方式是什么? (更新几十亿行表中的几百万行)

  1. 我应该写一个带连接的 UPDATE 语句吗?

  2. 删除这百万行并插入新行会更好吗?

  3. 任何其他方式,例如创建一个仅包含适当 INSERT 的新扩展事实表?

谢谢

埃里克

PS:我来自 SQL Server 背景,DELETE 可能很慢

PPS:我仍然喜欢 SQL Server! :-)

【问题讨论】:

  • Eric,如果您能确定表的键合并将比删除/插入十亿行更好,前提是您的表集群良好。
  • 我们对 Snowflake 来说“相对”是新手,到目前为止,我们还没有使用 Clustering,因为 Snowflake 应该开箱即用地做得很好......它说!看来我们应该多研究一下这方面

标签: snowflake-cloud-data-platform


【解决方案1】:

Snowflake 与传统 RDBS 的写入性能表现完全不同。您的所有表都保留在 S3 中,并且 S3 不允许您仅重写现有对象的选择字节;必须上传和替换整个文件对象。因此,虽然在数据和索引已就地修改的 SQL 服务器中,根据需要创建新页面,雪花中的 UPDATE/DELETE 是对表文件的完整顺序扫描,创建原始文件的不可变副本,并过滤掉适用的行(删除)或修改(更新),然后替换刚刚扫描的文件。

因此,无论是更新 1 行还是 1M 行,至少必须重写存在修改数据的整个微分区。

我会看一下MERGE 命令,它允许您在一个命令中插入、更新和删除所有内容(有效地将表 A 的差异应用到表 B 中。除此之外,它应该保留您的 @ 987654322@ 向下与不断擦除和重写表。另一个考虑是,由于雪花是面向列的,理论上列更新应该只需要对该列的 S3 文件进行操作,而插入/删除将替换所有 S3 文件对于所有列,这会降低性能。

【讨论】:

  • 有趣。根据您的回答和 Rajib 的评论,看来我们需要研究非自动聚类。非常感谢
  • 我认为 Snowflake 是混合列的,因此一行始终位于单个文件中,并且永远不会跨微分区文件拆分。这意味着,即使您正在更新单个列,它仍然需要重写相同数量的微分区,就好像您正在更新所有列一样。 dl.acm.org/doi/10.1145/2882903.2903741
  • @SimonD,看起来你是对的,我回去在一个文档中发现了一些东西,我有进一步支持你所说的话:“表被水平分割成大的、不可变的文件,相当于传统数据库系统中的块或页面。在每个文件中,每个属性或列的值都组合在一起并进行高度压缩,这是一种众所周知的方案,在文献中称为 PAX 或混合列式。”
  • "每个表文件都有一个表头,除了其他元数据之外,它还包含文件中每一列的偏移量。由于 S3 允许对部分文件进行 GET 请求,因此查询只需下载文件头和他们感兴趣的那些专栏。”因此,对于读取,雪花可以以柱状方式运行,但对于写入则不行。
  • 是的,我想我也读过。甚至还有一个 2018 年的 YouTube 视频,其中一位工程师也进行了解释。
猜你喜欢
  • 2019-10-22
  • 1970-01-01
  • 1970-01-01
  • 2010-11-22
  • 2019-06-28
  • 2013-11-27
  • 1970-01-01
  • 1970-01-01
  • 2011-04-30
相关资源
最近更新 更多