天天看點

大資料計算服務Maxcompute之--mapjoin原理和使用

大資料計算服務(maxcompute,原名 odps)是一種快速、完全托管的 gb/tb/pb 級資料倉庫解決方案。

<a href="https://help.aliyun.com/document_detail/27800.html?spm=5176.7840267.6.539.po3ivs">https://help.aliyun.com/document_detail/27800.html?spm=5176.7840267.6.539.po3ivs</a>

主要有三種操作資料的方式sql,udf,mapreduce,了解hadoop的同學就比較熟悉這些東西了。

由此可見實際上底層的計算都是依靠mapreduce這個計算引擎去執行。首先了解下什麼是mapreduce。一份資料很大的時候在maxcompute上是分布式存儲的,也就是會分開存放到很多伺服器,當一個任務執行的時候會從這些資料所在的伺服器上啟動一個程序讀取這些資料,進行計算等操作,還會啟動一個程序把這些資料進行彙總分析并輸出。那前者程序叫做map,後者程序叫做reduce,合起來叫mapreduce任務。

使用sql操作資料的時候,會經常用到join。比如select * from a a join b b on a.id=b.id,這句sql在轉換成mapreduce任務執行的時候:

1,map任務讀資料,并對兩個表的資料打上不同的tag用來區分

2,reduce端接收打标記的資料,将不同标記的表資料相同關聯字段的資料

假設有兩個表,我們暫且叫做big表和small表,其中big表資料量比較大,分布式存在n台執行個體伺服器上,small表存在于一台伺服器就放下了。

首選maxcompute會啟動一些map的程序(map任務)去讀取這些資料分别打上标記,map的個數是由一個參數控制的這裡暫時不解釋了。注意對于讀取big表的每個map任務有可能在其他伺服器上,那麼這時候就需要到資料所在的伺服器上把資料拉過來,small表也會啟動一個或者幾個map任務讀取檔案系統中的資料,讀取完成後會到reduce端接收資料進行關聯,判斷關聯字段相等的就放在一起輸出,達到關聯效果。

我們可以看一個例子,我準備了一個相對大的表train_user_lt,5g大小,資料大概7億條。

準備了一個比較小的表map_join_test,隻有3條資料。

執行了這句sql,如圖

大資料計算服務Maxcompute之--mapjoin原理和使用

從圖中可以看出分為三部分

1,大的表train_user_lt啟動了39個map任務去讀取資料707025259條

2,小的表啟動一個map任務讀取3條資料。

3,reduce階段接收了3+707025259=707025262條資料,輸出了707025259條資料,left outer join按照左邊的大表輸出。

但是看下消耗的時間是40分鐘,這樣來說算是很長的時間的。那麼怎麼優化提高速度呢,有沒有一種比較友善,比較直接暴力的方式進行優化呢

那麼本文的重點就來了--mapjoin:

mapjion會把小表全部讀入記憶體中,把小表拷貝多份分發到大表資料所在執行個體上的記憶體裡,在map階段直接拿另外一個表的資料和記憶體中表資料做比對,由于在map是進行了join操作,省去了reduce運作的效率會高很多。

使用的條件就是當一個大表和一個或多個小表做join時。sql會将使用者指定的小表全部加載到執行join操作的程式的記憶體中,進而加快join的執行速度。需要注意,在maxcompute使用mapjoin時:

left outer join的左表必須是大表;

right outer join的右表必須是大表;

inner join左表或右表均可以作為大表;

full outer join不能使用mapjoin;

mapjoin支援小表為子查詢;

使用mapjoin時需要引用小表或是子查詢時,需要引用别名;

在mapjoin中,可以使用不等值連接配接或者使用or連接配接多個條件;

目前maxcompute 在mapjoin中最多支援指定8張小表,否則報文法錯誤;

如果使用mapjoin,則所有小表占用的記憶體總和不得超過512mb。請注意由于maxcompute 是壓縮存儲,是以小表在被加載到記憶體後,資料大小會急劇膨脹。此處的512mb限制是加載到記憶體後的空間大小;

多個表join時,最左邊的兩個表不能同時是mapjoin的表。

那麼為什麼說left outer join的左表必須是大表呢,

因為左表是大表的時候,會拿小表的全部資料和大表所在的執行個體伺服器中的資料比對一遍,剛好小表就在記憶體裡。如果是左表是小表,那麼需要把大表所有的資料拉過來跟小表比對一遍,試想一下性能會如何。

來看下寫法

看下優化後的效果

大資料計算服務Maxcompute之--mapjoin原理和使用

任務變成了兩個部分,map端直接讀取資料和記憶體裡的小表進行關聯,然後輸出,少了一步reduce。也就是說關聯從reduce轉到map端進行join,省去了reduce這一步,是以叫做:mapjoin。

看下執行時間1分鐘20多秒。之前是40分鐘。當然我這邊測試是把兩個比較極端的資料進行比較,是以效果比較明顯。由此看來大表關聯小表的時候可以使用mapjoin進行優化查詢。

那麼mapjoin除了優化性能,還可以幹什麼呢。

maxcompute sql不支援支援在普通join的on條件中使用不等值表達式、or ,like等邏輯等複雜的join條件,但是在mapjoin中可以進行如上操作。例如

總結:mapjoin看似很小的操作變化,實際上可以帶來很大效率提升,另外還可以解決一些不等關聯的業務場景。

正如馬雲經常說的一句話:

small is beautiful,small is powerful !