postgresql , greenplum , dblink
greenplum在許多企業中被用于資料倉庫,一個企業中通常會有統一的使用者管理系統,賬務系統;還有許多業務線。
資料被分成兩類,一類是業務相關的,一類是全公司統一的資料。
如果使用者将兩個部分資料分别存入不同的資料庫(單個執行個體可以建立多個資料庫),并且公共資料需要與業務資料join時,你可能會想到dblink這個功能,通過dblink管理其他資料庫然後和本地資料進行join。

如果你對執行個體和資料庫的概念不太了解,可以參考一下這篇文檔。
<a href="https://github.com/digoal/blog/blob/master/201605/20160510_01.md">《postgresql 邏輯結構 和 權限體系 介紹》</a>
那麼到底dblink是否适合這個場景呢?
greenplum預設并沒有打包dblink,是以需要部署一下。
例如現在greenplum base postgresql是8.3的版本。
将dblink.so拷貝到所有節點的gp軟體目錄
需要使用dblink的資料庫,執行dblink.sql
建立2張測試表,注意他們的分布鍵,用于觀察。
分别插入100萬測試資料
redistribute motion 3:3,表示從3個節點重分布到3個節點,說明原始資料來自3個節點。
gather motion 3:1,表示從3個節點彙聚到1個節點,
從dblink結果的重分布資訊(1:3),可以分析出這樣的結論
1. 可以肯定的是,dblink并沒有在每個資料節點執行,但是在哪個資料節點執行的,從計劃上看不出來。
2. 由于dblink沒有在所有節點執行,意味着,如果dblink傳回的結果集很大的話,這個執行節點的壓力會較大。
從重分布執行計劃結果看,自定義函數也隻在某個節點被調用。
某些情況會報錯,例如: 當函數中有通路到資料庫表,并且需要與其他表進行join時。
從執行計劃可以看出,沒有gather motion節點,說明dblink函數和自定義函數就是在master節點執行的。
如果在資料節點執行,應該有gather motion節點,例如
分布式資料庫兩階段聚合的原理請參考
<a href="https://github.com/digoal/blog/blob/master/201305/20130502_01.md">《postgres-xc customized aggregate introduction》</a>
<a href="https://github.com/digoal/blog/blob/master/201608/20160825_02.md">《greenplum 最佳實踐 - 估值插件hll的使用(以及hll分式聚合函數優化)》</a>
目前dblink與普通的使用者自定義函數類似,并沒有和greenplum的mpp架構進行适配,它們會在master節點被調用,如果dblink傳回的結果集較大,master很容易成為瓶頸。
如果需要使用dblink與其他表進行join,流程是這樣的。
1. 首先會在master調用dblink,
2. dblink執行的結果集會收到master節點
3. master節點将結果集重分布到資料節點,
4. 然後再與其他表進行join。(好在join并不會在master節點執行。)
當然,我們不排除gpdb社群未來會改造dblink,來适配mpp的架構。但是至少目前還存在以上弊端,(除非dblink傳回的結果集很小,否則請謹慎使用)。
1. 建議資料放到一個資料庫中,使用不同的schema來區分不同的業務資料或公共資料。這樣的話在同一個資料庫中就可以任意的join了,對master無傷害。
2. 如果不同業務一定要使用多個資料庫,那麼建議使用外部表作為公共表,這樣做也不會傷害master,并且每個節點都可以并行的通路外部表的資料。
例如gpfdist外部表,阿裡雲hybriddb的oss外部表等。
外部表一旦寫入,就不可修改,如果公共資料經常變化,或者定期需要更新,(例如某些賬務系統,每天或定期會将使用者資訊更新到greenplum中)那麼建議使用一個字段來标示最新資料,同時低頻率的增量合并外部表。
例如
2.1. 隻寫 tbl_foreign_table_news(id int, xxx, xxx 最後更新時間)。
2.2. 低頻率的truncate tbl_foreign_table_origin,然後将tbl_foreign_table_news合并到 tbl_foreign_table_origin。
2.3. 使用者查詢tbl_foreign_table_origin即為公共資料。
3. 如果dblink擷取的結果集較小,那麼使用dblink作為臨時的方案,來實作執行個體内跨庫資料join是沒有太大問題的。