MaxCompute JOIN优化小结
摘要: Join是MaxCompute中最基本的語(yǔ)法,但由于數(shù)據(jù)量和傾斜問(wèn)題,非常容易出現(xiàn)性能問(wèn)題。一般情況下,join產(chǎn)生的問(wèn)題有兩大類(lèi): 數(shù)據(jù)傾斜問(wèn)題:join會(huì)將key相同的數(shù)據(jù)分發(fā)到同一個(gè)instance上處理,如果某個(gè)key上的數(shù)據(jù)量特別多則會(huì)導(dǎo)致該instance處理時(shí)間比其他instance…
原文地址:http://click.aliyun.com/m/43804/
Join是MaxCompute中最基本的語(yǔ)法,但由于數(shù)據(jù)量和傾斜問(wèn)題,非常容易出現(xiàn)性能問(wèn)題。一般情況下,join產(chǎn)生的問(wèn)題有兩大類(lèi):
1.數(shù)據(jù)傾斜問(wèn)題:join會(huì)將key相同的數(shù)據(jù)分發(fā)到同一個(gè)instance上處理,如果某個(gè)key上的數(shù)據(jù)量特別多則會(huì)導(dǎo)致該instance處理時(shí)間比其他instance處理時(shí)間長(zhǎng),這就是我們常說(shuō)的數(shù)據(jù)傾斜,這也是join計(jì)算性能問(wèn)題的罪魁禍?zhǔn)?#xff1b;
2.數(shù)據(jù)量問(wèn)題:關(guān)聯(lián)的兩表基本沒(méi)有熱點(diǎn)問(wèn)題,但兩個(gè)表數(shù)據(jù)量都非常大同樣會(huì)影響性能,比如記錄數(shù)達(dá)幾十億條,如商品表、庫(kù)存表等;
雖然MaxCompute中提供了一些通用的優(yōu)化算法,但從業(yè)務(wù)角度解決性能問(wèn)題往往更精確,更有效。對(duì)于MaxCompute sql優(yōu)化,在云棲社區(qū)上已經(jīng)有比較多的經(jīng)驗(yàn)積累,本文主要對(duì)join產(chǎn)生的性能問(wèn)題以及解法做些總結(jié)。
不同數(shù)據(jù)類(lèi)型key關(guān)聯(lián)
例子
瀏覽IPV日志以商品id關(guān)聯(lián)商品表,假設(shè)日志表的商品id字段是string類(lèi)型,商品表中的商品id是bigint類(lèi)型,那么在關(guān)聯(lián)中,關(guān)聯(lián)key會(huì)全部轉(zhuǎn)換成double類(lèi)型進(jìn)行比較,設(shè)想由于埋點(diǎn)問(wèn)題日志表中的商品id存在很多非數(shù)值的臟數(shù)據(jù),那么轉(zhuǎn)換成double后值都變?yōu)镹ULL或者截取前面的數(shù)值,關(guān)聯(lián)時(shí)就會(huì)產(chǎn)生數(shù)據(jù)傾斜問(wèn)題,更嚴(yán)重的會(huì)造成數(shù)據(jù)錯(cuò)誤。
解法
關(guān)聯(lián)時(shí)手工進(jìn)行數(shù)據(jù)格式轉(zhuǎn)換,在這種情況下一般將bigint類(lèi)型key轉(zhuǎn)換成string類(lèi)型。
select a.* from ipv_log_table a left outer join item_table b on a.item_id = cast(b.item_id as string)思考下,假如反過(guò)來(lái)將string類(lèi)型轉(zhuǎn)換成bigint、假如IPV日志表中的商品id大部分為無(wú)效值(比如0)、又假如IPV日志表中沒(méi)有無(wú)效值但是有熱點(diǎn)key會(huì)有什么問(wèn)題呢?下面的例子會(huì)解答這些問(wèn)題。
小表join大表
Join中存在小表,一般這個(gè)小表在100M以?xún)?nèi),可以用mapjoin,避免分發(fā)引起的長(zhǎng)尾。拿上面的例子來(lái)說(shuō),假如商品表數(shù)據(jù)量只有幾萬(wàn)條記錄(這里只是打個(gè)比方,現(xiàn)實(shí)業(yè)務(wù)中商品表一般都是非常龐大的),但是IPV日志表中的商品id 80%值為0的無(wú)效值,且記錄數(shù)有幾十億,如果采用上述SQL寫(xiě)法,數(shù)據(jù)傾斜是顯而易見(jiàn)的,但利用mapjoin可以有效解決這個(gè)問(wèn)題:
select /*+ MAPJOIN(b) */a.* from ipv_log_table a left outer join item_table b on a.item_id = cast(b.item_id as string)mapjoin原理
把小表廣播傳遞到所有的Join Task Instance上面,然后直接和大表做Hash Join,簡(jiǎn)單的說(shuō)就是將join操作提前到map端,而非reduce端。
mapjoin使用注意點(diǎn)
小表在left outer join 時(shí)只能是右表, right outer join 時(shí)只能是左表, inner join 時(shí)無(wú)限制,full outer join不支持mapjoin;
mapjoin最多只支持8張小表,否則會(huì)報(bào)語(yǔ)法錯(cuò)誤;
mapjoin所有小表內(nèi)存限制不能超過(guò)2GB,默認(rèn)為512M;
mapjoin支持小表為子查詢(xún);
mapjoin支持不等值連接或者使用or連接多個(gè)條件;
大表join大表存在無(wú)效值
在小表join大表時(shí)我們已經(jīng)了解到通過(guò)mapjoin將小表全部加載到map端可以解決傾斜問(wèn)題,但假如‘小表‘不夠小,mapjoin失效的時(shí)候該怎么辦呢?同樣以本文第一個(gè)場(chǎng)景為例,IPV日志表中80%商品id都為無(wú)效值0(目前MaxCompute底層已經(jīng)針對(duì)NULL值進(jìn)行優(yōu)化,已經(jīng)不存在傾斜問(wèn)題了),這時(shí)關(guān)聯(lián)十幾億量級(jí)商品表那就是個(gè)災(zāi)難。
解法1-分而治之:
我們可以事先知道無(wú)效值是不可能關(guān)聯(lián)出結(jié)果的,而且完全不需要參與關(guān)聯(lián),所以可以將無(wú)效值與有效值數(shù)據(jù)分開(kāi)處理:
解法2-隨機(jī)值打散:
我們也可以以隨機(jī)值代替NULL值作為join的key,這樣就從原來(lái)一個(gè)reduce來(lái)處理傾斜數(shù)據(jù)變成多reduce并行處理,因?yàn)闊o(wú)效值不參與關(guān)聯(lián),即使分發(fā)到不同reduce,也不會(huì)影響最終計(jì)算結(jié)果:
解法3-轉(zhuǎn)化為mapjoin:
雖然商品表有十幾億條記錄,不能直接通過(guò)mapjoin來(lái)處理,但在實(shí)際業(yè)務(wù)中,我們知道一天內(nèi)用戶(hù)訪問(wèn)的商品數(shù)是有限的,在業(yè)務(wù)中尤為明顯,基于此我們可以通過(guò)一些處理轉(zhuǎn)換成mapjoin:
解法對(duì)比
解法1和解法2是通用解決方案,對(duì)于解法1,日志表被讀取兩次,而解法2中只需讀取一次,另外任務(wù)數(shù)解法2也是少于解法1的,所以總的來(lái)看解法2是優(yōu)于解法1的。解法3是基于一定的假設(shè),隨著業(yè)務(wù)發(fā)展或者某些特殊情況下假設(shè)可能失效(比如一些爬蟲(chóng)日志,可造成訪問(wèn)商品數(shù)接近全量),這會(huì)導(dǎo)致mapjoin失效,所以在使用過(guò)程中要根據(jù)具體情況來(lái)評(píng)估。
一個(gè)古老的例子
最后要講一個(gè)古老的優(yōu)化case,雖然歷史比較久遠(yuǎn),目前已沒(méi)有相關(guān)問(wèn)題,但優(yōu)化思路值得借鑒。情況是這樣的,歷史上并存過(guò)兩套商品維表,一份主鍵是字符串id,新的商品表也就是目前在使用的主鍵是數(shù)字id,字符串id和數(shù)字id做了映射,存在商品表中的兩個(gè)字段中,所以在使用中需要分別過(guò)濾數(shù)字id、字符串id然后分別和商品表關(guān)聯(lián),最后union起來(lái)得到最終結(jié)果。
思考下如果換成下面的優(yōu)化思路是不是更優(yōu)呢?
select ... from ipv_log_table a join (select auction_id as auction_id from auctionsunion allselect auction_string_id as auction_id from auctions where auction_string_id is not null ) b on a.auction_id = b.auction_id答案是肯定的,可以看到優(yōu)化后商品表讀取從2次降為1次,IPV日志表同樣,另外MR作業(yè)數(shù)也從2個(gè)變?yōu)?個(gè)。
總結(jié)
對(duì)于MaxCompute sql優(yōu)化最有效的方式是從業(yè)務(wù)的角度切入,并能夠?qū)axCompute sql轉(zhuǎn)化為mapreduce程序來(lái)解讀。本文針對(duì)join中各種場(chǎng)景優(yōu)化都做了一些梳理,現(xiàn)實(shí)情況很可能是上述多場(chǎng)景的組合,這時(shí)候就需要靈活運(yùn)用相應(yīng)的優(yōu)化方法,舉一反三。
識(shí)別以下二維碼,干貨
總結(jié)
以上是生活随笔為你收集整理的MaxCompute JOIN优化小结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 让运维更高效:关于ECS系统事件
- 下一篇: 提升研发效率 保障数据安全——阿里云宣布