一、目的
1、
理解Greenplum中的數據分布策略(random 和 distribution),分析不同分布策略的優劣;
2、 理解查詢執行中的數據廣播和數據重分布,分析在何種情況下選擇哪種策略,以具體實驗驗證;
3、借助explain指令,分析select、join、group等常用sql語句的執行流程;
4、查看相關文檔理解SQL中窗口函數的語義,分析窗口函數的執行語義,以實驗驗證。
(復制)
二、 使用環境
主機數量:3台虛擬機,1台master單核2G內存,2台slave單核1.5G內存
虛擬機:VMware 10.0
操作系統:CentOS 6.7
Greenplum版本:4.3.99.00(PostgreSQL 8.3.23)
二、實驗過程
1、Greenplum數據分布策略random與hash-distribution
首先,創建一張原始表,輸入一些數據,不指定分布鍵,默認以第一列作為分布鍵。
可以修改分布鍵,按c3列分布。
插入一些數據,然后查看數據分布。
可以觀察到,按c3列的值進行哈希分布。c3=3的值全部分布到seg0,因此可以看出,若分布鍵不均勻,以hash分布的方式分布數據,存在數據偏移。
修改分布策略為隨機分布,查看數據分布。
咋一看,數據分布也不均勻,但是這可能是由於數據量過少,隨機分布出現的偏差。重新組織數據,再次查看,發現數據分布比較均勻了。而且,可以看到,c3=3的行被分散到不同的seg中去。
總結GP的分布策略,采用隨機的分布方式,數據分布較為均勻。按分布鍵的方式進行哈希分布,不一定能夠保證數據不會存在偏移,但是對於讀取數據應該較為友好。可以不必遍歷所有的seg節點。
2、數據廣播和數據重分布
關聯數據在不同節點上的,需要通過網絡流入到一個節點上執行連接操作,產生了數據遷移,GP中的數據遷移方式為數據廣播和數據重分布。
數據重分布,使用上次作業所導入的表,進行連接操作,發現查詢計划使用了數據重復布執行。
數據廣播,創建一個小表oders_replay,使其與大表做連接,發現查詢的執行方式變成數據廣播方式。
因此,總結上面GP策略的選擇上,若數據量相差比較大的情況下,將小表廣播到各個seg節點上,會執行的更快。若數據量基本相當,則使用數據重分布的方式,通常代價比較小。
3、sql執行流程
Select語句執行:
根據上圖所示,”select *,cume_dist() over(order by grade) from stugrade;”語句是一個嵌套循環查詢,循環內先做調用聚集函數。分布式執行過程采用Gather Motion(N:1)方式將所有子節點匯合數據到slice 1(master)上。順序掃描全表,按grade合並,再排序。
Join 語句執行:
上面的Join語句同樣是采用Gather Motion(N:1)方式遷移數據,之后采用hash join的方式進行連接。
Group 語句執行:
Group語句以grade屬性進行成組,統計各grade的人數,sql執行過程是,數據按grade鍵重分布,順序掃描stugrade表,然后使用hash方式是以grade屬性成組,最后遷移到一個節點進行統計返回結果。
4、窗口函數
窗口函數是只能在select語句中使用的一直函數類型,每一行返回一個值,結果按照當前行或行所對應的窗口分隔、框架來說明,使用時帶有over語句。所有窗口函數都使用over()語句作為條件,可在括號中指定應用的函數。
窗口函數表:
函數 |
返回類型 |
語法 |
描述 |
cume_dist() |
double precision |
CUME_DIST() OVER ( [PARTITION BY expr ] ORDER BY expr ) |
計算一組只中值的累計分布。具有相同值的行有相同的累計分布值。 |
dense_rank() |
bigint |
DENSE_RANK () OVER ( [PARTITION BY expr ] ORDER BY expr ) |
計算在一個無跳過的有序組中的行的排行值。 |
first_value(expr) |
same as input expr type |
FIRST_VALUE( expr ) OVER ( [PARTITION BY expr ] ORDER BY expr [ROWS|RANGE frame_expr ] ) |
返回一個有序集合中的第一個元素的值 |
lag(expr[,offset] [,default]) |
same as input expr type |
LAG( expr [, offset ] [, default ]) OVER ( [PARTITION BY expr ] ORDER BY expr ) |
提供一個訪問同一個表的多行數據,而不用做自連接。從查詢中返回一系列行的游標。LAG提供在給定偏移上的一行的訪問。默認偏移是1。如果偏移超過范圍,講返回默認值。若默認值沒有指定,則默認值為空。 |
last_value(expr) |
same as input expr type |
LAST_VALUE(expr) OVER ( [PARTITION BY expr ] ORDER BY expr [ROWS|RANGE frame_expr ] ) |
返回一個有序集合中的最后一個元素的值 |
lead(expr [,offset] [,default]) |
same as input expr type |
LEAD(expr [,offset] [,exprdefault]) OVER ( [PARTITION BY expr ] ORDER BY expr ) |
提供一個訪問同一個表的多行數據,而不用做自連接。從查詢中返回一系列行的游標。Lead提供在給定偏移上的一行的訪問。默認偏移是1。如果偏移超過范圍,講返回默認值。若默認值沒有指定,則默認值為空。 |
ntile(expr) |
bigint |
NTILE(expr) OVER ( [PARTITION BY expr ] ORDER BY expr ) |
將一個有序的數據集划分成若干桶(由表達式定義),假設每一行放進一個桶中。 |
percent_rank() |
double precision |
PERCENT_RANK () OVER ( [PARTITION BY expr ] ORDER BY expr ) |
計算在數據集中的百分比。 |
rank() |
bigint |
RANK () OVER ( [PARTITION BY expr ] ORDER BY expr ) |
計算一個有序組中的排名,相同值的排名相同,所以排名可能不連續。 |
row_number() |
bigint |
ROW_NUMBER () OVER ( [PARTITION BY expr ] ORDER BY expr ) |
將一個唯一的數字分配給分區中的每一行或這個查詢的每一行。 |
簡單的對上面的幾個窗口函數進行測試。
Row_number():
Rank():
Percent_rank(): 這里的百分比是指在之前n-1行的百分比累計值。相同行值的百分比值相同。
last_value(expr) 和first_value(expr):last取分區內最后一個元素,first區第一個元素。
Cume_dist():
5.附注
*