1. 程式人生 > >GreenPlum資料分佈策略

GreenPlum資料分佈策略

兩種分佈方式

在Greenplum資料庫中所有表都是分散式的,所以每一張表都會被切片,每個segment例項資料庫會存放相應的資料片段。切片(分佈)規則可以由使用者定義,可選的方案有根據使用者對每一張表指定的hash key進行的Hash分佈或者選擇隨機分佈。

Hash分佈

當選擇Hash分佈策略時,可以指定表的一列或者多列組合。greenplum會根據指定的Hash key列計算每一行資料對應的Hash值,並對映到相應的segment例項。當選擇的Hash key列的值唯一時,資料會均勻的分散至所有segment例項。 對於分佈鍵的選擇,有以下方式及行為: 1.指定分佈鍵,分佈鍵可以是表的一列或者多列組合,但不建議組合分佈鍵的列數超過兩列。 2.若表中存在主鍵,不能指定其他單列作為唯一主鍵,且對於組合分佈鍵,其中必須要包含主鍵,且主鍵必須要位於組合分佈鍵的第一列,否則會報錯。 3.若沒有指定分佈鍵,且表中沒有主鍵及唯一鍵,則預設使用第一列作為分佈鍵。 4.若沒有指定分佈鍵,且表中存在主鍵或唯一鍵(二者不能同時存在),則選擇主鍵或唯一鍵作為分佈鍵。 總結來說,對於分佈鍵的優先順序如下: 主鍵 > 指定分佈鍵 > 唯一鍵 > 未指定分佈鍵

隨機分佈

當選擇隨機分佈時,資料將會隨機分佈至segment,相同值的資料行不一定會分發至同一個segment。雖然隨機分佈可以確保資料平均分散至所有segment,但是在進行表關聯分析時,仍然會按照關聯鍵重分佈資料,所以隨機分佈策略通常不是一個明智的選擇(除非你的SQL只有對單表進行全域性的聚合操作,即沒有group by或者join等需要資料重分部的操作)。

資料分佈的最佳實踐

能致使資料被均勻分佈的最優分佈是Greenplum資料庫中最重要的因素。在一個MPP無共享環境中,一個查詢的總體響應時間由所有Segment的完成時間度量。整個系統和最慢的一個Segment一樣快。如果資料發生傾斜,擁有更多資料的Segment將需要更多時間完成,因此每一個Segment必須有大約相同資料量的行並且執行大概相同量級的處理。如果一個Segment比其他Segment有明顯更多的資料要處理,將會導致糟糕的效能和記憶體不足的情況。

在決定分佈策略時,考慮下列最佳實踐: 1.為所有的表明確定義一個分佈列或者隨機分佈。不要使用預設分佈。 2.理想情況下,使用單個將資料在所有Segment之間均勻分佈的列。 3.不要在查詢的WHERE子句中將要使用的列上進行分佈。 4.不要在日期或者時間戳上分佈。 5.分佈鍵列資料應該含有唯一值或者非常高的勢。 6.如果單個列無法實現均勻分佈,則使用多列分佈鍵,但不要超過兩列。額外的列值通常不會得到更均勻的分佈,而且它們要求額外的雜湊處理時間。 7.如果兩個列的分佈鍵無法實現資料的均勻分佈,則使用隨機分佈。大部分情況中的多列分佈鍵都要求移動操作來連線表,因此它們對於隨機分佈來說沒有優勢。

Greenplum資料庫的隨機分佈不是迴圈的,因此無法保證每個Segment上的記錄數相等。隨機分佈通常會落在變化低於10個百分點的目標範圍中。

在連線大型表時,最優分佈非常關鍵。為了執行連線,匹配的行必須位於同一個Segment上。如果資料沒有按照同一個連線列分佈,其中一個表中需要的行會被動態重新分佈到其他Segment上。在一些情況下會執行一次廣播移動而不是執行重新分佈移動。

關聯的廣播與重分佈

當兩張表關聯時,如果有一張表關聯鍵不是分佈鍵,那麼就會發生表的廣播或者重分佈,將資料移動到一個節點上進行關聯,從而獲得資料。 分散式的關聯有兩種: 單庫關聯:關聯鍵與分佈鍵一致,只需要在單個庫的關聯後得到結果即可。資料無需在segment間移動,只在各個segment上執行即可。 跨庫關聯:關聯鍵與分佈鍵不一致,資料需要重新分佈,轉換成單庫關聯,從而實現表的關聯。 通過下表中的兩個表來進行SQL分析

表名 欄位 分佈鍵 資料量
A id,id2 id M
B id,id2 id N
內連線

情況1:

select * from A,B where A.id=B.id;

分佈鍵與關聯鍵相同,屬於單庫關聯,不會造成廣播或者重分佈。

情況2:

select * from  A,B where A.id=B.id2;

表A的關聯鍵是分佈鍵,表B的關聯鍵不是分佈鍵,那麼可以通過兩種方法來實現表的關聯: 1.將表B按照id2欄位將資料重分佈到每一個節點上,然後再與表A進行關聯。重分佈的資料量是N 2.將表A廣播,每一個節點都放一份全量資料,然後再與表B關聯得到結果。廣播的資料量是 M * 節點數 所以當N>M * 節點數 的時候,選擇表A廣播,否則選擇表B重分佈。

情況3:

select * from A,B where A.id2=B.id2;

對於這種情況,兩個表的關聯鍵及分佈鍵都不一樣,那麼還有兩種做法: 1.將表A與表B都按照id2欄位,將資料重分佈到每個節點,重分佈的代價是M+N 2.將其中一個表廣播後再關聯,當然選取小表廣播,代價小,廣播的代價是 min(M,N) * 節點數 所以,當 N + M > min(M,N) * 節點數 的時候,選擇小表廣播,否則選擇兩個表都重分佈。

左連線:

情況1:

select * from A left join B on A.id=B.id;

單庫關聯,不涉及資料跨庫關聯。 情況2:

select * from A left join B on A.id=B.id2;

由於左表的分佈鍵是關聯鍵,鑑於左連線的性質,無論表B資料量多大,都必須將表B按照欄位id2重分佈資料。

情況3:

select * from A left join B on A.id2=B.id;

左表的關聯鍵不是分佈鍵,由於左連線A表肯定是不能被廣播的,所以有兩種方式:

1.將表A按照id2重分佈資料,轉換成情況A,代價為M 2.將表B廣播,代價為 N * 節點數 情況4:

select * from A left join B on A.id2=B.id2;

還是有兩種方式: 1.將表A與表B都按照id2欄位將資料重分佈一遍,轉換成情況1,代價是M+N 2.表A不能被廣播,只能將表B廣播,代價是 N * 節點數 對於有多種情況,greenplum總是選擇代價小的方式來執行sql。

全連線:

情況1:

select * from A full outer join B on A.id=B.id;

對於關聯鍵都是分佈鍵的情況,在gp中全連線只能採用Merger Join來實現

情況2:

select * from A full outer join B on A.id = B.id2;

將關聯鍵不是分佈鍵的表重分佈資料,轉換成情況1來解決。無論A、B大小分別為多少,為了實現全連線,不能將表廣播,只能是重分佈。

情況3:

select * from A full outer join B on A.id2=B.id2;

將兩張表都重分佈,轉換成情況1進行處理。