HIVE 调优1
業(yè)務(wù)背景
用戶軌跡工程的性能瓶頸一直是etract_track_info,其中耗時(shí)大戶主要在于trackinfo與pm_info進(jìn)行左關(guān)聯(lián)的環(huán)節(jié),trackinfo與pm_info兩張表均為GB級(jí)別,左關(guān)聯(lián)代碼塊如下:
[SQL]?純文本查看?復(fù)制代碼
?
| 1 2 3 | from trackinfo a left outer join pm_info b on (a.ext_field7 = b.id) |
使用以上代碼塊需要耗時(shí)1.5小時(shí)。
優(yōu)化流程
第一次優(yōu)化
考慮到pm_info表的id是bigint類型,trackinfo表的ext_field7是string類型,其關(guān)聯(lián)時(shí)數(shù)據(jù)類型不一致,默認(rèn)的hash操作會(huì)按bigint型的id進(jìn)行分配,這樣會(huì)導(dǎo)致所有string類型的ext_field7集中到一個(gè)reduce里面,因此,改為如下:
[SQL]?純文本查看?復(fù)制代碼
?
| 1 2 3 | from trackinfo a left outer join pm_info b on (cast(a.ext_field7 as bigint) = b.id) |
?
改動(dòng)為上面代碼后,效果仍然不理想,耗時(shí)為1.5小時(shí)。
?
第二次優(yōu)化
?
考慮到trackinfo表的ext_field7字段缺失率很高(為空、字段長度為零、字段填充了非整數(shù))情況,做進(jìn)行左關(guān)聯(lián)時(shí)空字段的關(guān)聯(lián)操作實(shí)際上沒有意義,因此,如果左表關(guān)聯(lián)字段ext_field7為無效字段,則不需要關(guān)聯(lián),因此,改為如下:
?
[Bash shell]?純文本查看?復(fù)制代碼
?
| 1 2 3 4 5 6 | from trackinfo a left outer join pm_info b on (a.ext_field7 is not null and length(a.ext_field7) > 0 and a.ext_field7 rlike '^[0-9]+$' and a.ext_field7 = b.id) |
上面代碼塊的作用是,如果左表關(guān)聯(lián)字段ext_field7為無效字段時(shí)(為空、字段長度為零、字段填充了非整數(shù)),不去關(guān)聯(lián)右表,由于空字段左關(guān)聯(lián)以后取到的右表字段仍然為null,所以不會(huì)影響結(jié)果。
改動(dòng)為上面代碼后,效果仍然不理想,耗時(shí)為50分鐘。
第三次優(yōu)化
想了很久,第二次優(yōu)化效果效果不理想的原因,其實(shí)是在左關(guān)聯(lián)中,雖然設(shè)置了左表關(guān)聯(lián)字段為空不去關(guān)聯(lián)右表,但是這樣做,左表中未關(guān)聯(lián)的記錄(ext_field7為空)將會(huì)全部聚集在一個(gè)reduce中進(jìn)行處理,體現(xiàn)為reduce進(jìn)度長時(shí)間處在99%。
換一種思路,解決辦法的突破點(diǎn)就在于如何把左表的未關(guān)聯(lián)記錄的key盡可能打散,因此可以這么做:若左表關(guān)聯(lián)字段無效(為空、字段長度為零、字段填充了非整數(shù)),則在關(guān)聯(lián)前將左表關(guān)聯(lián)字段設(shè)置為一個(gè)隨機(jī)數(shù),再去關(guān)聯(lián)右表,這么做的目的是即使是左表的未關(guān)聯(lián)記錄,它的key也分布得十分均勻
?
[SQL]?純文本查看?復(fù)制代碼
?
| 01 02 03 04 05 06 07 08 09 10 11 12 | from trackinfo a left outer join pm_info b on ( ????case when (a.ext_field7 is not null ????????and length(a.ext_field7) > 0 ????????and a.ext_field7 rlike '^[0-9]+$') ????then ????????cast(a.ext_field7 as bigint) ????else ????????cast(ceiling(rand() * -65535) as bigint) ????end = b.id ) |
第三次改動(dòng)后,耗時(shí)從50分鐘降為了1分鐘32秒,效果顯著!
?
總結(jié)