2014-12-03 53 views
0

我有一个有1.4B记录的大表。我每天都必须使用UPDATE语句像下面的(小,但不是非常小)来更新基于另一个表中的一些条件这个大表的一些记录:在Redshift中优化大表的更新

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。

所以我想知道如果我可以将此查询分解成多个分区查询。 join_field实际上是一个字母数字散列值,我可以看看字段的第一个字符,并使用LIKE在36个小块(0到9和A到Z)中运行语句。但我想知道是否有更好的方法。

回答

1

是的,我想说,你提到的分块查询将是你最好的选择。通常,最快的做法是使用OFFSETLIMIT以及ORDER BY的组合来完成此操作,以定义块,但使用非常大的有序OFFSET值本身可能是一个性能问题(因为它必须计算整个先订购,然后由于LIMITOFFSET),特别是考虑到您在表格中拥有的记录数量。但是,既然你声明你已经通过散列值对它们进行了分区,你可以唯一地进行迭代,我将简单地将它作为分块机制 - 它是内置的,并且应该给你更小的块与...合作。你可以考虑通过我之前提到的机制进一步细分这些块,如果它们仍然太大而不能很好地执行。

请注意,您可能需要在哈希列上有索引,以便它能够快速找到它们,尽管从纯粹的角度来看它们可能不会被使用,如果查询规划者决定需要太多的行退货(并且红移可能有其他差异)。

要进一步优化它,您可以考虑多线程一次执行多个更新。我经常为此使用GNU parallel工具,因为它可以快速简单地对shell命令进行多线程处理。这可以与psql客户端一起使用,我可以告诉它,在Redshift中支持。

注:

最终,我认为最好的整体选择将是对哈希值的每个第一字符,每个从主表继承了单独的表。这使得每个表可以单独在UPDATE中处理,而不必首先经历大的过滤操作等,但是仍然可以使用父表查询所有表(即,它不应该真正影响现有的SELECT报表)。

但是,这当然是一个更大的工作,现在可能不太可行,如果你要做这样的事情,你会想要与查询计划员等确认它确实是一个改善和没有红移这是不是一个好主意(我纯粹从Postgres的角度来讲)的具体原因。