如何在redshift中调试磁盘完整错误

首次使用Amazon的Redshift时,很快就会意识到它与其他关系数据库的不同。
您拥有诸如COPY和UNLOAD之类的新选项,并且失去了诸如关键约束之类的熟悉的帮助器。
与传统的数据库相比,您可以更快地处理更大的数据集,但是要充分利用它,需要学习。

我们在开始时遇到的一个问题是无助的磁盘已满错误,尤其是当我们知道我们有剩余磁盘空间时。
去年,我们收集了许多有关如何在Redshift中管理磁盘空间的资源。
我们将分享我们所学的知识,以帮助您快速调试自己的Redshift群集并充分利用它。

如果在运行查询时遇到磁盘已满错误,则肯定发生了一件事情-运行查询时,集群中的一个或多个节点磁盘空间不足。
这可能是因为查询使用了大量的内存并溢出到磁盘上,或者查询很好,并且集群的硬盘上有太多数据。
您可以通过查询stv_partitions表来查看表使用了多少空间,从而找出哪种情况。
我喜欢从FlyData使用此查询。

理想情况下,您不会使用超过70%mysql数据库同步 的容量。
即使在容量超过80%的情况下,Redshift仍可以继续正常工作,但是它仍然可能会引起您的问题。
如果您看起来有足够的空间,请继续下一节,但是如果您使用的空间超过90%,则肯定需要跳到“编码”部分。


如果失败的查询包含连接子句,则很可能是导致您出错的原因。
当Redshift执行联接时,它有几种策略可以将来自不同表的行连接在一起。
默认情况下,它通过在每个表中创建联接键的哈希值来执行“哈希联接”,然后将它们分配给集群中的每个其他节点。
这意味着每个节点将必须为表的每一行存储哈希。
当联接大表时,这会迅速填满磁盘空间。
但是,如果查询的两个联接键在同一节点上,则整个查询可以在不使用任何额外内存的情况下就地进行。
通过设置表以使它们的dist键相同,可以避免出现磁盘已满错误。
但是,在设置dist键时,请注意偏斜,这将在下一节中讨论。

如果由于dist键已针对其他查询进行了优化而无法更改dist键,则新键可能会导致偏斜问题或其他原因,您可能可以对查询进行一些更改,以便仍然可以执行。
您可以尝试以下一些方法:

使用子查询而不是联接。
一些使用联接的查询仅需要来自一个表的数据,但是正在使用联接来验证某些信息。
在这些情况下,联接通常可以用IN子句和子查询代替。
例如,对我们来说,一个常见的查询是获取有关订阅用户的一些信息。
除了选择两个表之外,我们还可以选择其ID在subscriptions表中的用户。
保留子查询的结果会占用一些内存,但通常比哈希联接所需的内存少得多。

创建并联接子表。
在许多情况下,我们仅从要联接的表中检索数据的一小部分子集,而对整个表进行哈希联接。
在这种情况下,您可以创建一个表,通常是一个临时表,该表是要连接的表的子集,但已应用了需要进行的任何筛选。
这样,通过连接两个小表,哈希值要小得多。
您甚至可以分发它们,以便根本没有哈希联接。
同样,此选项会占用一些内存,但比整个表的哈希联接要少得多。

如果您设置了dist键,则可能是在处理偏斜,这是表中一个节点上的行多于其他节点上的行。
即使在常规查询中,严重的偏差也可能导致磁盘已满错误,因为使用的任何额外磁盘空间都可能导致一个超载节点抛出错误。
来自Amazon的此查询非常适合检查倾斜的表。
如链接中所述,如果“偏斜”列中的值较高,或者“填充切片”列中的值较低,尤其是对于大型表,则可能需要重新考虑这些表的dist策略。

在群集上为大型表设置分布时,我们选择了一个键,该键具有大量可能的值,因此行应该在节点之间均匀分布。
但是,我们没有意识到的是,对于许多行,此列均为空。
然后,所有这些行都存储在群集的同一节点上,即使我们只使用了75%的磁盘空间,该节点也会在几乎所有查询中引发磁盘已满错误。

与传统的SQL数据库相比,Redshift的一个独特功能是可以对列进行编码以占用更少的空间。
但是,没有自动编码,因此用户必须选择在创建表时如何对列进行编码。
您可以在Amazon文档中阅读许多编码选项。
开始编码的最简单方法是使用Amazon的Python脚本分析表并获取建议。
如果磁盘空间不足,并且尚未对表进行编码,则可以通过这种方式恢复相当大的空间。
如果您已对表进行了编码,则值得检查svv_table_info表以查看是否已添加了未编码的任何表,或者重新运行上述脚本以查看是否应更改任何表的编码。

将新行添加到Redshift时,它们不会按指定的排序顺序添加,这对于某些编码类型起作用很重要,并且当删除行时,不会自动释放空间。
吸尘处理这两个问题。
在表上运行vacuum命令时,将对它进行排序,并释放已删除行使用的空间。
如果您从表中添加或删除了大量行,则对该表进行清理将释放一些空间。
您可以在此处阅读有关如何运行vacuum命令以及哪些选项的信息。

吸尘的想法来自Redshift的父项目Postgres,但是如果您熟悉Postgres,您可能会惊讶地发现吸尘不是自动发生的,并且该命令必须手动运行。
还值得注意的是一次只能抽一张桌子,因此您需要仔细安排抽真空时间。
To save you from having to vacuum, you should prefer dropping a table or using the “truncate” command rather than the “delete” command when deleting large amounts of data, since those commands automatically free up disk space and a vacuum won’t be 需要。

如果您按照本指南进行操作,希望您的群集上有足够的空间,并且不再看到磁盘已满的错误。
但是,如果仍然存在,实际上只剩下两个选择:删除数据或购买另一个节点。

不要害怕考虑删除数据。
我们有时会审核表并清除实验和现已失效的项目中使用的数据,从而节省了一些空间。
只要记住清理从中删除行的表即可。
如果您对管理Redshift集群有任何疑问,或者找到了另一种空间管理方法,请随时告诉我们。

猜你喜欢

转载自blog.csdn.net/weixin_49470452/article/details/107507055