GreenPlum是一個底層是多台PostgreSQL分表分庫的分布式數據庫,它有如下特點
- 支持標准SQL,幾乎所有PostgreSQL支持的SQL,greenplum都支持
- 支持ACID、分布式事務
- 支持上百台集群(這一點有點不好,hadoop可以萬台)
系統架構
Master Host
- 處理用戶請求,生成執行計划,以及在執行計划執行必要的聚合操作(avg)或者排序
- 內部有一個PostgreSQL數據庫,保存所有的元數據,索引信息
- 監控所有segment的狀態信息
Segment host
- 每台Segment host有多個segment,一般segment等於core數
- segment是一個PostgreSQL數據庫,負責存儲具體數據
內部網絡
GreenPlum內部使用udp網絡,但是Greenplum會對數據包進行校驗,因此可靠性等同於TCP。使用TCP的時候,最多支持1000個segment
執行計划
當master接受到一條SQL語句,會將這條語句解析為執行計划DAG,將DAG中不需要進行數據交換的划分為slice,多表連接,aggerate,sort的時候,都會涉及到slice的重分布,會有一個motion任務來執行數據的重分布。將slice下發到涉及到的相關segment中。
我認為slice類似與Spark中的stage的概念,不需要進行數據shuffle
motion方式
- gather motion(N->1):在master節點上把所有segment數據聚集起來,一般是sort,sort group,sort join
- boardcast motion(N->N):每個segment把數據廣播給其余所有segment
- redistribute motion(N->N):每個segment把數據按照hash的方式重新分布
我們可以猜一猜上面的執行計划代表什么:A表和B表進行join連接,然后它們又進行sort或者聚合。
算子實現
索引
Greenplum支持所有postgresql的索引,另外還支持位圖索引
Join方式
- Hash join:
- nestloop join:笛卡兒積必須nestloog join
- merge join
分布式事務
Greenplum雖然是面向OLAP的數據庫,但是也提供了插入,刪除,更新數據的接口,利用兩階段提交協議支持分布式事務,提供強一致性,支持ACID,支持的隔離級別是(讀已提交,可串行化)。
Greenplum采用和Postgresql類似的方式,上層事務塊控制事務狀態轉換,底層事務負責執行具體的語句以及和相關segment交互。
與單機事務相比,多了TBLOCK_PREPARE狀態,代表兩階段提交協議中的中間狀態。除此之外,分布式事務也有一套以DXT開頭的分布式狀態
例子
正常流程
-
在所有segment都啟動一個事務塊,狀態TBLOCK_BEGIN
-
執行一條插入語句,狀態TBLOCK_INPRGRESS
- END命令,狀態為DXT_STATE_PREPARED。這里master狀態為TBLOCK_END,slave segment狀態為TBLOCK_DEFAULT(初始狀態)
- 第二階段,開始正式提交。DXT_STATE_PREPARED->DXT_STATE_INSGRETE_FORGET_COMMIT。master狀態為TBLOCK_END->TBLOCK_DEFATULT,slave segmeng又重新經歷一輪所有狀態
容錯
slave segment容錯
每台segment都在其他機器上有備機
Primary Segment 與對應 Mirror Segment 之間的數據基於文件級別同步備份。Mirror Segment 不直接參與數據庫事務和控制操作。
為什么采用文件同步的機制:mirror庫數據直接獲取primary的文件(日志文件)和數據(修改的數據頁)。
恢復流程
發生宕機時,greenplum有兩種恢復模式,"read-only"和"continue"。
- read-only:也就是說如果一個segment壞了,整個greenplum會變成只讀,不能寫了
- continue:由mirror正常提供服務,master節點會把新增數據記錄下來,等待primary恢復后同步
primary segment容錯
基於數據流通過WAL同步,由postgresql提供的容錯。
負載均衡和數據組織方式
數據組織方式
- 有一類特殊的表,稱為append-only表,支持列存儲,表壓縮
- 通過gpfdist插件,可以支持外部表
負載均衡
Greenplum通過分布和分區的方式,使得龐大的數據分布在不同的segment上。嚴格來說,分布才是拆表,分區只是為了加快查詢速度。
- 分布:是從物理上把數據分散到各個SEGMENT上,Greennplum提供hash函數
- 分區:segment內部按照規則將數據組織在一起
分布
- hash分布:distributed by (column_name),可以指定多個分布鍵。相同的hash值分布到同一個segment
- 隨機分布:distributed randomly,相同的記錄可能分布到不同的segment
建議:
- 分布列盡量選擇需要經常JOIN的列,這類查詢的並發越高,越應該考慮
- 盡量選擇分布均勻的列,或者多列
- 不要輕易使用隨機分布
分區
- range partition:按照數據的范圍
- list partition:按照List中的值
- 多級分區
建議:
- 盡量選擇和查詢條件相關的字段,縮小QUERY需要掃描的數據
- 當有多個查詢條件時,可以使用子分區,進一步縮小需要掃描的數據
資源控制
- 限制正在執行的所以SQL的最大cost
- 限制最多運行多少SQL
- 控制正在運行的SQL的優先級