第六章 Greenplum 高級(jí)應(yīng)用
[TOC]
本章將介紹一些 Greenplum 的高級(jí)特性缝驳,主要是與其他關(guān)系型數(shù)據(jù)庫(kù)有區(qū)別的地方。
當(dāng)今的數(shù)據(jù)處理大致可以分成兩大類(lèi):聯(lián)機(jī)事務(wù)處理OLTP(On-Line Transaction Processing)呢灶、聯(lián)機(jī)分析處理OLAP(On-Line Analytical Processing)摘仅。OLTP是傳統(tǒng)的關(guān)系型數(shù)據(jù)庫(kù)的主要應(yīng)用踏施,主要是基本的应又、日常的事務(wù)處理宙项。OLAP是數(shù)據(jù)倉(cāng)庫(kù)系統(tǒng)的主要應(yīng)用,支持復(fù)雜的分析操作株扛,側(cè)重決策支持尤筐,并且提供直觀易懂的查詢(xún)結(jié)果汇荐。
表6-1列出OLTP與OLAP之間的比較
6.1 Appendonly 表與壓縮表
6.1.1 應(yīng)用場(chǎng)景及語(yǔ)法介紹
壓縮表必須是Appendonly表,是只能不斷追加的表盆繁,不能進(jìn)行更新和刪除掀淘。
(1)壓縮表的應(yīng)用場(chǎng)景
- 業(yè)務(wù)上不需要對(duì)表進(jìn)行更新和刪除操作,用truncate + insert 就可以實(shí)現(xiàn)業(yè)務(wù)邏輯
- 訪問(wèn)表的時(shí)候基本上是全表掃描油昂,不需要在表上建立索引
- 不能經(jīng)常對(duì)表進(jìn)行加字段或修改字段類(lèi)型革娄,對(duì)Appendonly表加字段比普通表慢很多
(2)語(yǔ)法介紹
建表的時(shí)候加上 with(appendonly=true) 就可以指定表是Appendonly表。如果需要建壓縮表冕碟,則加上 with(appendonly=true,compresslevel=5)拦惋,其中compresslevel是壓縮率,取值為1~9鸣哀,一般選擇5就足夠架忌。
6.1.2 壓縮表的性能差異
由于數(shù)據(jù)倉(cāng)庫(kù)的大部分應(yīng)用都是IO密集型的吞彤,每次的查詢(xún)基本上都是全表掃描我衬,大量的順序讀寫(xiě)。
一張簡(jiǎn)單的商品表饰恕,總數(shù)據(jù)量500萬(wàn)條挠羔,常見(jiàn)的數(shù)據(jù)類(lèi)型有date、numeric埋嵌、integer破加、varchar、text等雹嗦,普通表與壓縮表性能比較結(jié)果如表6-3:
6.1.3 Appendonly 表特性
對(duì)于每一張Appendonly表范舀,創(chuàng)建的時(shí)候都附帶創(chuàng)建一張pg_aoseg模式下的額表,表名一般是 pg_aoseg_ + 表的oid了罪,這張表中保存了這張Appendonly表的一些原數(shù)據(jù)信息锭环。
這個(gè)表的每個(gè)字段信息如表6-4:
在第四章中,介紹了一個(gè)函數(shù) gp_dist_random泊藕,通過(guò)這個(gè)函數(shù)辅辩,可以查詢(xún)子節(jié)點(diǎn)的信息,可以知道gp 底層每個(gè)數(shù)據(jù)節(jié)點(diǎn)的數(shù)據(jù)量娃圆、數(shù)據(jù)文件大小的情況玫锋,這樣我們就能夠分析表的數(shù)據(jù)分布情況、算出傾斜率等讼呢。
基于 pg_aoseg_ 這個(gè)表 :
- get_ao_compression_ratio:查詢(xún)壓縮表的壓縮率
- get_ao_distribution:查詢(xún)每個(gè)子節(jié)點(diǎn)的數(shù)據(jù)量
基于 Appendonly 表撩鹿,開(kāi)發(fā)了兩個(gè) gp的函數(shù):
- get_table_count:獲取Appendonly表的行數(shù),Appendonly表有一個(gè)字段用于保存這些信息悦屏,支持分區(qū)表三痰。
- get_table_info :用于獲取更加詳盡的表的信息吧寺,有表的行數(shù)、大小散劫、數(shù)據(jù)傾斜率(最大節(jié)點(diǎn)數(shù)據(jù)量/平均節(jié)點(diǎn)數(shù)據(jù)量)稚机、壓縮率。對(duì)于非分區(qū)表获搏,就只有一行數(shù)據(jù)赖条;對(duì)于分區(qū)表,但一行則是所有分區(qū)的匯總數(shù)據(jù)常熙,其他是每一個(gè)分區(qū)的具體信息纬乍,效果如圖6-1:
6.1.4 相關(guān)數(shù)據(jù)字典
在gp3.* 中,aoseg表的信息記錄在 pg_class 中的relaosegrelid 字典中裸卫,可用以下sql進(jìn)行查詢(xún):
select relaosegrelid from pg_class where relname='test01';
在gp4.*中仿贬,pg_class的relaosegrelid 字段已經(jīng)取消,aoseg表的信息保留在pg_appendonly 表中的segrelid字段中墓贿。
6.2 列存儲(chǔ)
Appendonly表還有一種特殊的形式茧泪,就是列存儲(chǔ)。
6.2.1 應(yīng)用場(chǎng)景
列存儲(chǔ)一般適用于寬表(即字段非常多的表)聋袋。在使用列存儲(chǔ)時(shí)队伟,同一個(gè)字段的數(shù)據(jù)都連續(xù)保存在一個(gè)物理文件中,所以列存儲(chǔ)的壓縮率已普通壓縮表的壓縮率要高的多幽勒,另外在多數(shù)字段中篩選其中幾個(gè)字段時(shí)嗜侮,需要掃描的數(shù)據(jù)量很小,掃描速度比較快啥容。因此锈颗,列存儲(chǔ)尤其適合在寬表中部分字段進(jìn)行篩選的場(chǎng)景。
6.2.2 數(shù)據(jù)文件存儲(chǔ)特性
列存儲(chǔ)在物理上存儲(chǔ)咪惠,一個(gè)列對(duì)應(yīng)一個(gè)數(shù)據(jù)文件击吱,文件名是原文件名加上 .n(n是一個(gè)數(shù)字)的形式來(lái)表示的,第一個(gè)字段硝逢,n=1姨拥,第二個(gè)字段n=129,以后每增加一個(gè)字段渠鸽,n都會(huì)增加128.
為什么每增加一個(gè)字段叫乌,n不是遞增的而是中間要間隔128個(gè)數(shù)字呢?這大概是由于徽缚,在gp中憨奸,每一個(gè)數(shù)據(jù)文件最大是1GB,如果一個(gè)字段在一個(gè)Segment中的數(shù)據(jù)量超過(guò)1GB凿试,就要重新生成一個(gè)新的文件排宰,每個(gè)字段中間剩余的這127個(gè)數(shù)字似芝,就是預(yù)留給組隊(duì)內(nèi)容很大,單個(gè)文件1GB放不下板甘,拆分成多個(gè)文件時(shí)党瓮,可以使用預(yù)留的127個(gè)數(shù)字為數(shù)據(jù)文件編號(hào)。
從這個(gè)物理的存儲(chǔ)特性就可以很明顯地看多列存儲(chǔ)的缺點(diǎn)盐类,那就是會(huì)產(chǎn)生大量的小文件寞奸,假設(shè)一個(gè)集群中有30個(gè)節(jié)點(diǎn),我們建一張有100個(gè)字段寬表的在跳,假設(shè)這張表是按照每天分區(qū)的一張分布表枪萄,保留了一年的數(shù)據(jù),那么將會(huì)產(chǎn)生的文件數(shù)是:
即產(chǎn)生將近110萬(wàn)的文件猫妙,這樣我們對(duì)一個(gè)表進(jìn)行DDL操作就會(huì)比較慢瓷翻,所以,列存儲(chǔ)應(yīng)該在合適的場(chǎng)景下才能使用割坠,而不能濫用列存儲(chǔ)齐帚,否則會(huì)得不償失
6.2.3 如何使用列存儲(chǔ)
列存儲(chǔ)的表必須是appendonly表,創(chuàng)建一個(gè)列存儲(chǔ)的表只需要在創(chuàng)建表的時(shí)候韭脊,在 with 子句中加入 appendonly=true,ORIENTATION=column 即可童谒。一般 appendonly 表會(huì)結(jié)合壓縮一起使用单旁,在 with 子句中增加 compresslevel=5 啟用壓縮.
6.2.4 性能比較
簡(jiǎn)單比較一下列存儲(chǔ)和普通壓縮表在性能上的區(qū)別沪羔。由于列存儲(chǔ)主要應(yīng)用在寬表上,故這次測(cè)試都是針對(duì)字段比較多的表象浑。
測(cè)試結(jié)果:
通過(guò)表6-6可以看出:
- 完全隨機(jī)的數(shù)據(jù)壓縮率比較低蔫饰,使用兩種方式的壓縮結(jié)果差不多
- 當(dāng)只查詢(xún)表的數(shù)據(jù)量的時(shí)候,普通壓縮表需要全表掃描愉豺,但是列存儲(chǔ)只需要查詢(xún)其中一個(gè)字段篓吁,速度非常快
- 隨著查詢(xún)字段的增加蚪拦,普通壓縮表查詢(xún)的速度基本上變動(dòng)不大杖剪,因?yàn)閽呙璧臄?shù)據(jù)量沒(méi)有變化。而列存儲(chǔ)則隨著查詢(xún)的字段增加驰贷,消耗時(shí)間增長(zhǎng)明顯
- 在測(cè)試的時(shí)候瓶頸在于磁盤(pán)的IO盛嘿,這是因?yàn)闇y(cè)試集群磁盤(pán)性能較差。在CPU消耗上括袒,列存儲(chǔ)的消耗略大于普通表的消耗次兆。
采用這兩種數(shù)據(jù)方式加載數(shù)據(jù)時(shí)都使用外部表,加載時(shí)的瓶頸在于文件服務(wù)器的網(wǎng)卡锹锰,所以使用這兩種方式進(jìn)行數(shù)據(jù)加載的速度都差不多
通過(guò)表6-7的結(jié)果可以看出芥炭,測(cè)試的結(jié)果與測(cè)試數(shù)據(jù)1的結(jié)果大致相同漓库,區(qū)別主要是:
- 測(cè)試的數(shù)據(jù)是真實(shí)的數(shù)據(jù),每個(gè)字段的內(nèi)容都會(huì)有些相似园蝠,當(dāng)每個(gè)字段的數(shù)據(jù)比較相似時(shí)渺蒿,使用列存儲(chǔ),這樣在壓縮文件時(shí)彪薛,可以獲得更高的壓縮率蘸嘶,節(jié)省磁盤(pán)的空間占用。
- 瓶頸還是磁盤(pán)IO陪汽,由于列存儲(chǔ)有更好的壓縮率训唱,所以在查詢(xún)?nèi)孔侄蔚那闆r下,列存儲(chǔ)消耗的時(shí)間還是比普通壓縮表小很多的挚冤。
6.3 外部表高級(jí)應(yīng)用
6.3.1 外部表實(shí)現(xiàn)原理
gpfdist 可以看做一個(gè)http服務(wù)况增,當(dāng)我們啟動(dòng) gpfdist 時(shí),可以用 wget 命令去下載 gpfdist 的文件训挡,將創(chuàng)建外部表命令時(shí)使用的url地址中的gpfdist 換成 http 即可澳骤,如:
wget http://10.20.151.59:8081/inc/1.dat -o 2.dat
當(dāng)查詢(xún)外部表時(shí),所有的Segment都會(huì)連上 gpfdist澜薄,然后 gpfdist 將數(shù)據(jù)隨機(jī)分發(fā)給每個(gè)節(jié)點(diǎn)为肮。
gpfdist 的架構(gòu)如圖6-2 所示:
1、gpfdist 的工作流程
- 啟動(dòng) gpfdist肤京,并在 Master 上建表颊艳。表建好之后并沒(méi)有任何的數(shù)據(jù)流動(dòng),只是定義好了外部表的原數(shù)據(jù)信息忘分。
- 將外部表插入到一張 Gp 的物理表中棋枕,開(kāi)始導(dǎo)入數(shù)據(jù)。
- Segment 根據(jù)建表時(shí)定義的 gpfdist url 個(gè)數(shù)妒峦,啟動(dòng)相同的并發(fā)到 gpfdist 獲取數(shù)據(jù)重斑,其中每個(gè) Segment 節(jié)點(diǎn)都會(huì)連接到 gpfdist 上獲取數(shù)據(jù)。
- gpfdist 收到 Segment 的連接并要接收數(shù)據(jù)時(shí)開(kāi)始讀取文件肯骇,順序讀取文件窥浪,然后將文件拆分成多個(gè)塊,隨機(jī)拋給 Segment笛丙。
- 由于 gpfdist 并不知道數(shù)據(jù)庫(kù)中有多少個(gè) Segment漾脂,數(shù)據(jù)是按照哪個(gè)分布鍵拆分的,因此數(shù)據(jù)是隨機(jī)發(fā)送到每個(gè) Segment 上的若债,數(shù)據(jù)到達(dá) Segment 的時(shí)間基本上是隨機(jī)的符相,所以外部表可以看成是一張隨機(jī)分布的表,將數(shù)據(jù)插入到物理表的時(shí)候,需要進(jìn)行一次重分布啊终。
- 為了提高性能镜豹,數(shù)據(jù)讀取與重分布是同時(shí)進(jìn)行的,當(dāng)數(shù)據(jù)重分布完成后蓝牲,整個(gè)數(shù)據(jù)導(dǎo)入流程結(jié)束趟脂。
2、gpfdist 最主要的功能
- 負(fù)載均衡:每個(gè) Segment 分配到的數(shù)據(jù)都是隨機(jī)的例衍,所以每個(gè)節(jié)點(diǎn)的負(fù)載都非常均衡昔期。
- 并發(fā)讀取,性能高:每臺(tái) Segment 都同時(shí)通過(guò)網(wǎng)卡到文件服務(wù)器獲取數(shù)據(jù)佛玄,并發(fā)讀取硼一,從而獲取了比較高的性能。相對(duì)于 copy 命令梦抢,數(shù)據(jù)要通過(guò) Master 流入般贼,使用外部表就消除了 Master 這個(gè)單點(diǎn)問(wèn)題。
3奥吩、如何提高 gpfdist 性能
想提高一個(gè)工具的性能哼蛆,首先要了解這個(gè)工具使用的瓶頸在哪里。對(duì)于數(shù)據(jù)導(dǎo)入霞赫,衡量性能最重要的就是數(shù)據(jù)分發(fā)時(shí)的吞吐腮介,其中有兩個(gè)地方容易成為瓶頸。
(1)文件服務(wù)器
一般文件服務(wù)器比較容易出現(xiàn)瓶頸端衰,因?yàn)樗械?Segment 都連接到這個(gè)節(jié)點(diǎn)上獲取數(shù)據(jù)叠洗,所以如果文件服務(wù)器是單機(jī)的,那么就很容易在磁盤(pán) IO 和網(wǎng)卡上出現(xiàn)瓶頸靴迫。
對(duì)于文件服務(wù)器惕味,當(dāng)磁盤(pán) IO 出現(xiàn)瓶頸時(shí):
- 使用磁盤(pán)陣列來(lái)提高磁盤(pán)的吞吐能力
- 采用分布式文件系統(tǒng)來(lái)提高整體的性能
對(duì)于網(wǎng)卡出現(xiàn)瓶頸:
- 更換網(wǎng)卡為萬(wàn)兆網(wǎng)卡楼誓,需要各環(huán)節(jié)的網(wǎng)絡(luò)環(huán)節(jié)滿(mǎn)足條件玉锌,如交換機(jī)支持等
- 通過(guò)多網(wǎng)卡機(jī)制來(lái)保證。如圖6-3疟羹,將文件拆分成多個(gè)文件主守,并啟動(dòng)多個(gè) gpfdist 分別讀取不同的文件,然后將 gpfdist 綁定到不同的網(wǎng)卡上以提高性能榄融。
在創(chuàng)建表的時(shí)候指定多個(gè) gpfdist 的地址参淫,例如:
CREATE EXTERNAL TABLE table_name
( column_name data_type [, ...] | LIKE other_table )
LOCATION ('gpfdist://filehostip1[:port1]/file_pattern1',
'gpfdist://filehostip2[:port2]/file_pattern2',
'gpfdist://filehostip3[:port3]/file_pattern3',
'gpfdist://filehostip4[:port4]/file_pattern4')
......
當(dāng)然我們也可以只啟動(dòng)一個(gè) gpfdist,但是通過(guò)不同的 ip 連接到 gpfdist 上愧杯,這樣讀取文件的 gpfdist 只有一個(gè)涎才,不能實(shí)現(xiàn) IO 的并發(fā),但是網(wǎng)卡卻可以使用多張,從而來(lái)消除單網(wǎng)卡的瓶頸耍铜。
6.3.2 可寫(xiě)外部表
前面介紹的是只讀外部表邑闺,在 gp 中,還有一種可寫(xiě)外部表棕兼。
語(yǔ)法如下:
CREATE WRITABLE EXTERNAL TABLE table_name
( column_name data_type [, ...] | LIKE other_talbe )
LOCATION ('gpfdist://outputhost[:port]/fillename'[, ...]) | ('gpfdist://hdfs_host[:port]/path')
FORMAT 'TEXT'
[( [DELIMITER [AS] 'delimiter']
[NULL [AS] 'null string']
[ESCAPE [AS] 'escape' | 'OFF'] )]
| 'CSV'
[([QUETE [AS] 'quote']
[DELIMITER [AS] 'delimiter']
[NULL [AS] 'null string']
[FORCE QUOTE column [, ...]]
[ESCAPE [AS] 'escape'] )]
[ ENCODING 'write_encoding' ]
[DISTRIBUTED BY (column, [ ... ] ) | DISTRIBUTED RANDOMLY]
在語(yǔ)法上可寫(xiě)外部表與普通外部表主要有兩個(gè)地方不一樣:
- 可寫(xiě)外部表沒(méi)有錯(cuò)誤表陡舅,不能指定允許有多少行數(shù)據(jù)錯(cuò)誤。因?yàn)橥獠勘淼臄?shù)據(jù)一般是從數(shù)據(jù)庫(kù)的一張表中導(dǎo)出的伴挚,格式肯定是正確的靶衍,一般不會(huì)有異常數(shù)據(jù)。
- 可寫(xiě)外部表在建表時(shí)可以指定分布鍵茎芋,如果不指定分布鍵颅眶,默認(rèn)為隨機(jī)分布(distributed randomly)。盡量采用與原表一致的分布鍵田弥。
使用可寫(xiě)外部表的注意事項(xiàng):
- 可寫(xiě)外部表不能中斷(truncate)帚呼。當(dāng)我們將數(shù)據(jù)寫(xiě)入可寫(xiě)外部表時(shí),如果可寫(xiě)外部表中途斷開(kāi)了要想重新運(yùn)行必須手動(dòng)將原有的文件刪除皱蹦,否則那一部分?jǐn)?shù)據(jù)會(huì)重復(fù)煤杀。
- 可寫(xiě)外部表指定的分布鍵應(yīng)該與原表的分布鍵一致,避免多余的數(shù)據(jù)重分布沪哺。
- gpfdist 必須使用 gp 4.x 之后的版本沈自。可寫(xiě)外部表是 gp 4.x 之后加入的新功能辜妓,在其他機(jī)器上啟動(dòng) gpfdist枯途,只需要將 $GPHOME/bin/gpfdist 復(fù)制過(guò)去即可。
6.3.3 HDFS外部表
gp 可以直接讀取 HDFS 文件籍滴,這樣可以將 gp 和 HDFS 整合在一起酪夷,將 gp 作為一個(gè)計(jì)算節(jié)點(diǎn),計(jì)算后的數(shù)據(jù)可以直接寫(xiě)入到 HDFS 中孽惰,提供對(duì)外的服務(wù)晚岭。HDFS 外部表的架構(gòu)圖如圖6-4。
下面將對(duì) gp4.2 以上版本的 HDFS外部表介紹勋功。
在 gp 4.2 及以上版本安裝坦报、配置 HDFS外部表的步驟如下:
- 在所有 Segment 上安裝 Java 1.6 或以上版本。
- gp 數(shù)據(jù)庫(kù)包括一下與 Hadoop 相關(guān)版本:
- Provatal HD 1.0(gphd-2.0):Hadoop 2.0 版本
- Greenplum HD(gphd-1.0,gphd-1.1 和 gphd-1.2):默認(rèn)版本狂鞋,使用其他組件可以通過(guò)設(shè)置 gp_hadoop_targetversion 這個(gè)參數(shù)進(jìn)行切換片择。
- Greenplum MR 組件(gpmr-1.0 和 gpmr-1.2):Greenplum 版本的 Mapreduce。
- Cloudera Hadoop 版本連接(cdh3u2 和 cdh4.1):Cloudera 版本的 Hadoop骚揍。
- 需要讀者自己安裝 Hadoop(Gp 只支持以上所列的版本)字管,安裝之后,需確保 gp 的系統(tǒng)用戶(hù)有讀和執(zhí)行 Hadoop 相關(guān) lib 庫(kù)的權(quán)限。
- 設(shè)置環(huán)境變量 JAVA_HOME嘲叔、HADOOP_HOME脐供。
- 設(shè)置 gp_hadoop_target_version 和 gp_hadoop_home 參數(shù)如表6-9:
- 重啟數(shù)據(jù)庫(kù):在使用 HDFS外部表的時(shí)候
- 有兩層權(quán)限關(guān)系:
- 對(duì) gp 的 HDFS 的使用用戶(hù)賦予 SELECT 和 INSERT 權(quán)限:GRENT INSERT ON PROTOCOL gphdfs TO gpadmin;
- 確保 gp 對(duì)應(yīng)的 OS用戶(hù)有 Hadoop 上 HDFS 文件的讀寫(xiě)權(quán)限。
- gp 在 HDFS 上支持三種文件格式:
- Text借跪,文本格式政己,同時(shí)支持讀寫(xiě)
- gphdfs_import,只支持只讀外部表掏愁。
- gphdfs_export歇由,只支持可寫(xiě)外部表。
- 有兩層權(quán)限關(guān)系:
創(chuàng)建外部表進(jìn)行讀裙邸:
CREATE readable EXTERNAL TABLE hdfs_test_read (id int,name varchar(128))
LOCATION ('gphdfs://10.20.151.7:9000/data/gpext/hdfs_test.dat')
FORMAT 'TEXT' (DELIMITER ',');
select * from hdfs_test_read;
id | name
---------------
104 | john
101 | tom
103 | marry
102 | cat
在 $GPHOME/lib/hadoop 目錄下沦泌,gp 自帶了各種 Hadoop 版本的 jar 包,這些包中定義了 gphdfs_import 跟 gphdfs_export 的數(shù)據(jù)格式辛掠。gp 在讀寫(xiě)這種格式的時(shí)候谢谦,需要自己編寫(xiě) MapReduce 任務(wù)。
6.3.4 可執(zhí)行外部表
可執(zhí)行外部表的語(yǔ)法如下:
CREATE [READABLE] EXTERNAL WEB TABLE table_name ( column_name data_type [, ...] | LIKE other_table )
LOCATION ('http://webhost[:port]/path/file' [, ...])
| EXECUTE 'command' [ON ALL
| MASTER
| number_of_segments
| HOST ['segment_hostname']
| SEGMENT segment_id ]
FORMAT 'TEXT'
[( [HERDER]
[DELIMITER [AS] 'delimiter' | 'OFF']
[NULL [AS] 'null string']
[ESCAPE [AS] 'escape' | 'OFF']
[NEWLINE [AS] 'LF' | 'CR' | 'CRLF']
[FILL MISSING FIELDS])]
| 'CSV'
[( [HEADER]
[QUOTE [AS] 'delimiter']
[NULL [AS] 'null string']
[FORCE NOT NULL column [, ...]]
[ESCAPE [AS] 'null string']
[NEWLINE [AS] 'LF' | 'CR' | 'CRLF']
[FILL MISSING FIELDS])]
[ ENCODING 'encoding' ]
[ [LOG ERRORS INTO error_talbe] SEGMENT REJECT LIMIT count
[ROWS | PERCEND] ]
在使用外部表時(shí)萝衩,每個(gè) Segment 的參數(shù)可能會(huì)略有不同回挽,或者是在腳本中需要獲取一些系統(tǒng)的參數(shù)。表6-10是 gp 自帶的一些常見(jiàn)參數(shù)猩谊,可以供腳本使用千劈。
6.4 自定義函數(shù)——各個(gè)編程接口
6.4.1 pl/pgsql
相比起 Oracle 的 pl/sql ,pl/pgsql 主要有如下限制:
- 最大的子事務(wù)個(gè)數(shù)只能是100牌捷,每一個(gè)異常捕獲墙牌,都會(huì)造成一個(gè)子事務(wù)。
- 在函數(shù)執(zhí)行的過(guò)程中不能執(zhí)行 commit暗甥。
- 由于不能執(zhí)行 commit喜滨,因此一個(gè)函數(shù)中不要處理太多的邏輯皆刺,否則容易導(dǎo)致程序出錯(cuò)喉钢,這一點(diǎn)與 oracle 不一樣允青。如果有比較復(fù)雜的邏輯要以外部的 shell 調(diào)用來(lái)實(shí)現(xiàn)昵济,不要在函數(shù)中實(shí)現(xiàn)。
- 所有的 pl/pgsql 都必須以函數(shù)的形式存在户辫,沒(méi)有 oracle 中存儲(chǔ)過(guò)程的概念闹司,所以每次使用都必須建立函數(shù),然后再執(zhí)行這個(gè)函數(shù)剥懒,使用起來(lái)不方便。
6.4.2 C 語(yǔ)言接口
6.4.2 plpython
6.5 Greenplum MapReduce
MapReduce 是 Google 提出的一種海量數(shù)據(jù)并發(fā)處理的一種編程思想合敦,可以讓程序員在多態(tài)機(jī)器上快速的編寫(xiě)出自己的代碼初橘。MapReduce 的基本思想是將大數(shù)據(jù)量拆分成一行一行 (key,value) 對(duì),然后分發(fā)給 Map 模塊,通過(guò)自定義的 Map 函數(shù)保檐,生成新的 (key,value) 對(duì)耕蝉,通過(guò)排序匯總,生成 (key,output_list) 發(fā)給自定義的 Reduce 函數(shù)處理夜只,每一個(gè) Reduce 函數(shù)處理一個(gè)唯一的 key 及這個(gè) key 對(duì)應(yīng)的所有 value 的列表垒在,如果有需要,還可以將 Reduce 的結(jié)果作為下一個(gè) Map 的數(shù)據(jù)再進(jìn)行計(jì)算扔亥。每一個(gè)機(jī)器都可以啟動(dòng)多個(gè) Map 和 Reduce 來(lái)計(jì)算結(jié)果场躯。
gp MapReduce 允許用戶(hù)自己編寫(xiě) map 和 reduce 函數(shù),然后提交給 gp 并發(fā)處理引擎處理旅挤,gp 在分布式的環(huán)境下允許 MapReduce 代碼踢关,并處理所有Segment 的報(bào)錯(cuò)信息。
gp 中的 MapReduce 基本框架如圖:
MapReduce 的組成部分:
在 gp 中粘茄,執(zhí)行 MapReduce 函數(shù)需要編寫(xiě) yaml 文件签舞。在 yaml 文件中,主要有以下幾個(gè)部分需要定義:
1柒瓣、INPUT
INPUT 有多種類(lèi)型:可以是一個(gè)外部文本數(shù)據(jù)文件儒搭、一個(gè)數(shù)據(jù)庫(kù)中的表或查詢(xún)等。
(1)外部文件
- INPUT:
NAME: my_file_input
FILE: seghostname:/var/data/gpfiles/employees.txt
COLUMNS
- first_name text
- last_name text
- dept text
FORMAT: TEXT
DELIMITER: |
(2)數(shù)據(jù)庫(kù)表
- INPUT:
NAME: my_table_input
TABLE: sales
(3)數(shù)據(jù)庫(kù)查詢(xún)
- INPUT:
NAME: my_query_input
QUERY: SELECT vendor, amt FROM sales WHERE region='usa';
(4)通過(guò) gpfdist 導(dǎo)入外部文件
- INPUT:
NAME: my_distributed_input
# specifiles the host,port and the desired files served
# by gpfdist. /* denotes all files on the gpfdist server
GPFDIST:
- gpfdisthost:8080/*
COLUMNS
- first_name text
- last_name text
FORMAT: TEXT
DELIMITER: '|'
(5)操作系統(tǒng)命令
- INPUT:
NAME: my_query_input
EXEC: /var/load_scripts/get_log_data.sh
COLUMNS
- url text
- date timestamp
FORMAT: TEXT
DELIMITER: '|'
類(lèi)型(4)和(5)也可以采用在數(shù)據(jù)庫(kù)中建成外部表的形式芙贫,就是可以當(dāng)成數(shù)據(jù)庫(kù)中的表操作师妙,跟(2)一樣,這兩個(gè)類(lèi)型的功能跟外部表有點(diǎn)重復(fù)屹培。
2默穴、Map
Map 是輸入一行數(shù)據(jù),有 0 個(gè)或多個(gè)數(shù)據(jù)輸出褪秀,可以用 python 或 perl 實(shí)現(xiàn)蓄诽。
3、Reduce
也可以用 python 或 perl 實(shí)現(xiàn)媒吗。
gp 提供幾個(gè)預(yù)定義 Reduce 函數(shù):
IDENTITY - 返回沒(méi)有標(biāo)紅的 (key,value) 對(duì)
SUM - 計(jì)算數(shù)字類(lèi)型的和
AVG - 計(jì)算數(shù)字類(lèi)型的平均值
COUNT - 計(jì)算輸入數(shù)據(jù)的count數(shù)
MIN - 計(jì)算數(shù)字類(lèi)型的最小值
MAX - 計(jì)算數(shù)字類(lèi)型的最大值
(函數(shù)對(duì) value 進(jìn)行相應(yīng)的操作)
4仑氛、OUTPUT
OUTPUT 可以是數(shù)據(jù)表也可以是文本文件:
(1)輸出到文本文件
- OUTPUT:
NAME: gpmr_output
FILE: /var/data/mapreduce/wordcount.out
(2)輸出到數(shù)據(jù)表
- OUTPUT
NAME: gpmr_output
TABLE: wordcount_out
KEYS:
- value
MODE: REPLACE(注:若是放此表并重建表,則用 REPLACE闸英,若是想追加輸出的數(shù)據(jù)锯岖,則用 APPEND)
5、Task
Task 的描述是選擇性的甫何,主要用在多級(jí)的 MapReduce 任務(wù)中出吹,一個(gè) Task 的輸出可以作為下一個(gè) Task 或 Map 的輸入。
6辙喂、EXECUTE
EXECUTE 就是將上面定義的步驟串聯(lián)起來(lái)
EXECUTE:
- RUN:
SOURCE: input_or_task_name
TARGET: output_name
MAP: map_function_name
REDUCE: reduce_function_name
6.6 小結(jié)
本章介紹了 gp 的一些高級(jí)的特性:
- 壓縮表:對(duì)數(shù)據(jù)采用壓縮存儲(chǔ)的方法捶牢,可以利用 CPU 來(lái)節(jié)省存儲(chǔ)空間鸠珠,降低 IO 的消耗,對(duì)于數(shù)據(jù)庫(kù)應(yīng)用性能有著重要的影響秋麸。
- 列存儲(chǔ):一種特殊的壓縮表渐排,將數(shù)據(jù)按列存儲(chǔ),可以提升壓縮率灸蟆,對(duì)于數(shù)據(jù)庫(kù)這種 IO 密集型的應(yīng)用驯耻,可以大大提升性能。但是列存儲(chǔ)同時(shí)也帶來(lái)了大量的小文件炒考,會(huì)對(duì)文件系統(tǒng)造成一定的壓力可缚,故不能大規(guī)模使用。
- 外部表:gp 通過(guò)外部表可以非常方便地進(jìn)行數(shù)據(jù)的導(dǎo)入導(dǎo)出票腰,通過(guò)并行處理城看,性能非常高⌒游浚可執(zhí)行外部表表提供了一種可拓展的方法测柠,使得數(shù)據(jù)導(dǎo)入導(dǎo)出更加靈活。同時(shí) gp 還通過(guò)提供與 HDFS 快速交互的方式缘滥,使數(shù)據(jù)庫(kù)與 Hadoop 可以靈活地結(jié)合在一起使用轰胁。
- 自定義函數(shù):要使數(shù)據(jù)庫(kù)使用起來(lái)更加方便,自定義函數(shù)在拓展 sql 上有著很重要的作用朝扼,通過(guò)自定義函數(shù)赃阀,再結(jié)合 sql,可以實(shí)現(xiàn)很多功能擎颖。
- MapReduce:當(dāng)下非常流行的一種編程思想榛斯,它簡(jiǎn)化了編程模型,通過(guò)這種編程思路搂捧,可以解決很多 sql 無(wú)法完成的功能驮俗。