在Redshift中优化大表的UPDATE

时间:2014-12-03 04:12:05

标签: postgresql amazon-redshift

我有一张1.4B记录的大表。每天我必须使用UPDATE语句基于另一个表(较小但不是很小)中的某些条件来更新这个大表的一些记录,如下所示:

UPDATE my_large_table set a_field_that_needs_to_be_updated = 1 WHERE join_field IN (SELECT join_field FROM another_table where some_other_conditions

这有时超过30分钟,这是我们的超时值,因此作业将被中止。

  1. 一个简单的解决方案是增加超时值,但这不是我想要的路线。
  2. 另一个优化可能是在两个表模式中使用join_field作为distkey,但是有更常见的连接用例,因此另一个字段被设置为distkey。
  3. 所以我想知道我是否可以将此查询分解为多个分区查询。 join_field实际上是一个字母数字哈希值,我可以看一下该字段的第一个字符,并使用LIKE以36个较小的部分(0到9和A到Z)运行该语句。但我想知道是否有更好的方法。

1 个答案:

答案 0 :(得分:1)

是的,我会说如你提到的那样对查询进行分块将是你最好的选择。通常情况下,最快的方法是将OFFSETLIMITORDER BY结合使用,以定义块,但使用非常大的有序OFFSET值本身就是一个性能问题(因为它必须首先计算整个订单,然后是LIMITOFFSET),特别是考虑到表中的记录数量。

但是,既然你已经说过你已经通过哈希值对它们进行了分区,你可以对它进行唯一迭代,那么我只需要将它作为分块机制 - 它内置了,并且应该给你更小的块来工作用。您可以考虑通过我之前提到的机制进一步细分这些块,如果它们仍然太大而不能很好地运行。

请注意,您可能需要在哈希列上安装索引,以便能够快速找到它们,但是从纯 Postgres 的角度来看,如果查询规划器决定太多,则可能无法使用它们需要返回行( Redshift 可能有其他差异)。

为了进一步优化它,您可以考虑多线程一次进行多个更新。我经常使用GNU parallel工具,因为它允许shell命令的快速和简单的多线程。这可以与 psql 客户端一起使用,我可以说,在 Redshift 中支持它。

注意:

最终,我认为最好的整体赌注是为哈希值的每个第一个字符分别设置表,每个表都从主表继承。这使得每个表都可以在UPDATE中单独处理,而不必先进行大型过滤操作等,但您仍然可以使用父表查询所有表(即它不应该真的会影响现有的SELECT语句。

但是,这肯定是一项更大的工作,现在可能无法做到,如果您要做这样的事情,您需要验证查询计划器等,这确实是一个改进并且没有 Redshift 具体原因,这不是一个好主意(我纯粹是从 Postgres 的角度来讲)。