2014-12-03 54 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的角度來講)的具體原因。