聊一聊Greenplum與PostgreSQL

資料庫工作筆記發表於2023-11-09

來源:PostgreSQL學徒

前言

Greenplum,在MPP領域常青不凋,又同為PostgreSQL系,加之Greenplum 7前些天也釋出了,於是近些天我將由陳淼編著的《Greenplum-Database管理員指南6.2.1》這本PDF看完了,這本著作包含作者十多年的經驗與心得,閱讀完之後收穫很大,在此也簡單聊聊個人的心得與見解。

常青樹

Greenplum從物理層面來看,整個叢集內含有多個PostgreSQL例項,大號的PostgreSQL,節點之間的資訊互動透過高速網際網路絡實現,透過將資料分佈到多個節點上來實現規模資料的儲存,再透過多個計算節點協同計算處理來提高查詢效能。

整體架構如下:

  1. master節點主要儲存後設資料,負責執行計劃的生成與查詢接入
  2. segment節點即計算節點,負責儲存實際資料的儲存以及分散式執行計劃的執行
  3. interconnect network,高速內聯網路,主要用於叢集間的通訊與資料重分佈

聊一聊Greenplum與PostgreSQL

Greenplum主要還是用於AP領域,雖然最新版已經基於12的核心,但是相較於Citus、PGXC系接入層可橫向擴充套件的架構,master目前還無法橫向擴充套件,即單master節點,TP能力上限取決於單master的瓶頸,所以不妨稱為"大AP小TP",畢竟我始終認為HTAP是有側重點的,要麼AP強TP弱點,要麼TP拿手AP弱勢。

分佈鍵

由於資料是分散儲存在多個計算節點中,因此不難理解,查詢會涉及到多個計算節點的協同,那麼如何預防"木桶效應"、"短板效應"是能否用好Greenplum的關鍵因素之一,即資料分佈情況,假如分佈鍵 (分佈鍵決定了資料如何分佈) 的選擇不理想,比如資料分佈不均,那麼按照HASH策略分佈的話,資料便會集中儲存在某幾個計算節點中,這樣就會造成"一人有難,他人圍觀"的尷尬局面,其中一個節點忙的熱火朝天,其他節點無所事事。

聊一聊Greenplum與PostgreSQL

其次就是多表關聯,也與分佈鍵息息相關,假如參與關聯的表的分佈鍵相同 (當然資料型別也要一致),那麼可以在計算節點本地就完成關聯操作,因為不同分佈鍵,資料分佈策略也不同,那麼就需要涉及到資料的移動 (在Greenplum中叫做Motion運算元),不難想象,要移動的資料量越多,對於interconnect也是個很大的挑戰,因此GPADMIN書中也提及:

必須使用萬兆網路作為內部網際網路絡,否則,一定會遭受很多網路方面的困擾。

這個機制也適用於其他需要設計分佈鍵的資料庫。

當然Greenplum也可能會選擇將資料進行"廣播",有類似的代價引數:gp_motion_cost_startup、gp_motion_cost_per_row以決定是廣播還是重分佈。如果單個欄位不能實現資料均勻分佈,則考慮使⽤兩個欄位做分佈鍵 (當然前提是關聯條件最好都包括這兩個欄位)。作為分佈鍵的欄位最好不要超過兩個。Greenplum使⽤雜湊進⾏資料分佈,使⽤更多的欄位通常不能得到更均勻的分佈,反⽽耗費更多的時間計算。

但是實際業務可能千差萬別,嚴格要求按照表的分佈鍵來進行關聯也不太現實,因此Greenplum還提供了複製表,即在每個計算節點上都有一份全量資料,類似於citus中的參考表,有了複製表,與複製表關聯的話,就不會涉及到資料庫的motion了,但是危害也是明顯的,由於每個節點都有一份全量副本,因此不適合大量更新,存在寫放大。

另外一種分佈策略是隨機分佈,顧名思義,資料的分佈是隨機的,即便你是同樣的分佈鍵,資料也可能分佈在不同的節點,這樣就會涉及到資料的motion。因此除非追求極致的均勻分佈 (官方說誤差不超過10%),不建議使用隨機分佈。

儲存引擎

另外一個需要提交的儲存引擎,Greenplum支援Heap、AOCO、AORO。Heap即PostgreSQL堆表,因此鎖模式也是相同,但是在GP6以前,還沒有全域性死鎖檢測機制,所以DELETE/UPDATE獲取的是Exclusive Lock,因此DELETE/UPDATE無法並行,序列執行。

聊一聊Greenplum與PostgreSQL

從6版本以後,引入了全域性死鎖檢測機制,Greenplum Heap和PostgreSQL的鎖矩陣模式一樣,至於本地死鎖檢測則還是deadlock_timeout。

再說回AO表,最開始設計時,AO表被稱為Append Only表,只支援追加新元組。在後來的迭代中,也支援了刪除和更新元組操作,因此現在AO表指的是Append Optimized,AO表又可細分為行存和列存。AP領域當然離不開列存,行存由於是以行為形式組織儲存,當需要讀取某列時,需要將這列前面的所有列都進行解析,所以訪問第一列和訪問最後一列的成本實際上是不一樣的,而列存顧名思義,以列為形式組織儲存,並且由於是同一型別的資料,壓縮也能更加高效,壓縮比更高。另外AP領域查詢通常只涉及到某些列,在這些列上進行聚合,count之類的操作,列存的優勢就出來了,非常適合向量計算、JIT架構,對大批次資料計算更高效,但是劣勢也不言而喻,參照之前的文章 Greenplum AO表儲存分析,不適合頻繁的寫入更新,寫放大很嚴重,並且一旦搭配分割槽表,那可能是災難性的後果,一個列一個檔案,一個分割槽一個數量,那麼整個分割槽表檔案數量為:

檔案數量  = 分割槽數量 * 列數量 * 計算節點數量

對於檔案系統,都可能先不堪重負尿了。這一點和單機PostgreSQL是類似的,分割槽表數量都要嚴格控制,尤其是PostgreSQL12以前的版本,另外在Greenplum中是不建議使用多級分割槽的。至於鎖模式,AO表的UPDATE/DELETE都是Exclusive Lock,因此需要序列。

所以儲存引擎的選擇在建模的時候就要選擇好,否則就要匯入匯出重寫了。

索引

其次是索引,在AP領域,由於資料量龐大,百億資料很常見,建個索引是十分吃力的,並且有時返回的資料量也很大,動輒幾十個欄位group by,這個時候索引可能就派不上用場,目前我看Greenplum還沒有"虛擬索引"的概念,因此在評估是否需要建立索引時,一定要衡量好索引的選擇率,以及對資源的取捨,不然建幾個小時結果還是個garbage那就虧大了,Greenplum更加註重多個節點協同平行計算。另外還支援Bitmap索引,適用於那種欄位重複值較高的場景。十分喜歡bytebytego的這種圖:

聊一聊Greenplum與PostgreSQL

安裝部署

在閱讀GPADMIN安裝部署章節之後,給我的感觸也挺多。

傳統集中式資料庫追求的是時延,因此儲存都會選擇高階全閃SAN或者NVME SSD,而AP領域資料量大,就AP以及我目前接觸到的領域而言,選擇的大都是機械盤 + 組RAID的形式,一般選擇RAID 5 + 熱備盤,條帶化選擇256KB。因為機械盤的故障率相較SSD要高得多,可以配置一個熱備盤以儘快接替故障盤。其次還需要配置IO排程策略,不過SATA口當年是慢速裝置的口,就一個提交佇列,再怎麼電梯排程一樣延時也很高,然而現在的NVME最大65536個佇列 + blkmq 之後,IO排程演算法都成浮雲了,按照摩爾定律,現在NVME SSD的價格也已降了很多,後面隨著硬體的不斷革命,條件允許還是上SSD吧。

其次是SWAP的設定,和集中式資料庫儘可能關閉SWAP機制不同,Greenplum主要需要考慮當計算節點主節點掛了之後,將mirror映象節點切換為新主之後,記憶體不足的情況,因此需要配置SWAP (比如原來某個主機上存在4個主節點 + 4個mirror,現在啟用了其中一個mirror為主節點,那麼對記憶體和CPU的消耗就更多),這也是計算傾斜的情形之一。

一般的通用方案是,SWAP的尺寸和RAM相同。

但是在計算其他記憶體引數的時候,比如gp_vmem_protect_limit,不能將SWAP當做記憶體參與計算,在叢集健康的情況下,永遠不要考慮SWAP。

其次是其他元件都要考慮高可用,比如內聯網路做冗餘,採用bond4,提升可用性和健壯性。因此,運維Greenplum會經常與網路打交道,什麼丟包、亂序都是十分麻煩的。

資料建模

Greenplum在建模上,與傳統集中式資料庫也存在很大差異,使⽤⾮規範化資料庫模式處理MPP分析型業務時,Greenplum資料庫表現優異。按照數倉領域的術語來說,採用大資料量很少變化的事實表 + 若干個小資料量維度表的雪花模型和星型模型設計會更好

聊一聊Greenplum與PostgreSQL

其次是位元組對齊,這個和PostgreSQL堆表是類似的,我在SQL最佳化文章中也提及過,合理地排列列的順序可以提升效能、降低儲存,何樂而不為。

聊一聊Greenplum與PostgreSQL

小結

再次感謝作者——陳淼,無私奉獻這麼優質的著作,我在閱讀過程中也發現了文件中的一些蟲子亦或是筆誤,並且也得到了作者及時的正向反饋,淼哥也即時進行了修訂,版本迭代。假如各位有從事Greenplum相關的工作,Greenplum Database管理員指南十分值得一看。

總而言之,Greenplum雖然同為PostgreSQL系的產品,但是還是有諸多差異,但用好分散式是個技術活。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70027826/viewspace-2993598/,如需轉載,請註明出處,否則將追究法律責任。

相關文章