哪个在 redshift 中性能更高 - 截断后跟 Insert Into 或 Drop and Create Table As?

Posted

技术标签:

【中文标题】哪个在 redshift 中性能更高 - 截断后跟 Insert Into 或 Drop and Create Table As?【英文标题】:Which one is more performant in redshift - Truncate followed with Insert Into or Drop and Create Table As? 【发布时间】:2021-01-07 05:49:20 【问题描述】:

我一直在研究 AWS Redshift,有点好奇哪种数据加载(完全重新加载)方法的性能更高。

方法 1(使用截断):

    截断现有表 使用 Insert Into Select 语句加载数据

方法 2(使用拖放和创建):

    删除现有表 使用 Create Table As Select 语句加载数据

我们一直在 ETL 中使用这两种方法,但我有兴趣了解 AWS 方面的幕后情况。

在我看来 - Drop and Create Table As 语句的性能应该更高,因为它减少了为 Insert Into 语句所需的表扫描/处理关联数据块的开销。 此外,AWS Redshift 中的 truncate 不会重新设置身份列 - Redshift Truncate table and reset Identity?

请分享你的想法。

【问题讨论】:

感谢@MarkB 的建议!我无法在这两种方法之间找到显着的性能差异,因此想了解每种方法在 Redshift 方面发生的情况。 也就是说,在许多情况下,删除和创建表似乎稍快一些。但不知道为什么。 【参考方案1】:

Redshift 在 1MB 块上运行,作为存储和一致性的基本单元。当对表进行更改时,这些块将被“发布”以供所有人查看何时提交更改。表只是组成它的块 id 的列表(数据结构),因为随时可能有许多版本的表在运行中(如果在其他人查看时正在更改它)。

为了这个问题,我们假设有问题的表很大(包含大量数据),我希望这是真的。这两个语句最终执行了一个共同的操作 - 取消链接并释放表中的所有块。这些块是所有数据存在的地方,因此您会认为这两者的速度是相同的,并且在空闲系统上它们很接近。两者都会自动提交结果,因此在工作完成之前命令不会完成。在这个空闲系统比较中,我看到 DROP 运行得更快,但是您需要再次创建表,因此需要时间来重新创建表的数据结构,但这可以在事务块中,所以我们需要包含 COMMIT ?最重要的是,在空闲系统中,这两种方法在运行时非常接近,当我上次为客户测量它们时,DROP 方法要快一些。我建议您在做出决定之前继续阅读。

但是,在现实世界中,Redshift 集群很少处于空闲状态,并且在负载情况下,这两个语句可能完全不同。 DROP 需要对表进行独占控制,因为它不在事务块内运行。在执行 DROP 之前,必须关闭(提交或回滚)表的所有其他用途。因此,如果您在表上执行此 DROP/recreate 过程,其他人正在使用 DROP 语句将被阻止,直到所有这些使用完成。这可能需要一段不确定的时间才能发生。对于“隐藏”或“未发布”表的 ETL 处理,DROP/recreate 方法可以工作,但您需要非常小心哪些其他会话正在访问相关表。

Truncate 确实在事务内部运行,但在完成时执行提交。这意味着它不会被使用该表的其他人阻止。只是表的一个版本是满的(对于那些在 truncate 运行之前查看它的人),一个版本是完全空的。表的数据结构具有打开它的每个会话的版本,并且每个会话都会看到与其版本相对应的块(或缺少块)。我怀疑它正在管理这些数据结构并通过提交队列传播这些更改,这会稍微减慢 TRUNCATE - 簿记。这种记账的好处是 TRUNCATE 不会被读取表格的其他会话阻塞。

在这些方法之间进行选择的决定性因素通常不是性能,而是哪一种具有适用于您的解决方案的锁定和一致性功能。

【讨论】:

非常感谢@billweiner 的精彩解释!这很有道理。对于您的问题,这种加载数据的方法将用于创建中间表,以帮助构建要插入最终表的数据。因此,通常没有人会直接访问这些表。因此,不必担心会话锁定表。更多的是寻找一种系统开销更少的方法。 最终表将在增量加载的情况下使用删除/插入或在完整数据刷新的情况下使用临时表更改表重命名。

以上是关于哪个在 redshift 中性能更高 - 截断后跟 Insert Into 或 Drop and Create Table As?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法在通过 Glue 插入 Redshift 时简单地截断列?

Spark 2.0.0 使用 jdbc 从 Redshift 表中截断

在 Redshift 中更新整个表的正确方法,删除表 + 创建表与截断 + 插入表

为啥 Amazon Redshift 会截断此 JSON 浮点数据的精度?

如何防止Redshift记录查询

以下哪个代码在 ASP.NET 2.0 中性能更好