HIVE 调优1
業務背景
用戶軌跡工程的性能瓶頸一直是etract_track_info,其中耗時大戶主要在于trackinfo與pm_info進行左關聯的環節,trackinfo與pm_info兩張表均為GB級別,左關聯代碼塊如下:
[SQL]?純文本查看?復制代碼
?
| 1 2 3 | from trackinfo a left outer join pm_info b on (a.ext_field7 = b.id) |
使用以上代碼塊需要耗時1.5小時。
優化流程
第一次優化
考慮到pm_info表的id是bigint類型,trackinfo表的ext_field7是string類型,其關聯時數據類型不一致,默認的hash操作會按bigint型的id進行分配,這樣會導致所有string類型的ext_field7集中到一個reduce里面,因此,改為如下:
[SQL]?純文本查看?復制代碼
?
| 1 2 3 | from trackinfo a left outer join pm_info b on (cast(a.ext_field7 as bigint) = b.id) |
?
改動為上面代碼后,效果仍然不理想,耗時為1.5小時。
?
第二次優化
?
考慮到trackinfo表的ext_field7字段缺失率很高(為空、字段長度為零、字段填充了非整數)情況,做進行左關聯時空字段的關聯操作實際上沒有意義,因此,如果左表關聯字段ext_field7為無效字段,則不需要關聯,因此,改為如下:
?
[Bash shell]?純文本查看?復制代碼
?
| 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) |
上面代碼塊的作用是,如果左表關聯字段ext_field7為無效字段時(為空、字段長度為零、字段填充了非整數),不去關聯右表,由于空字段左關聯以后取到的右表字段仍然為null,所以不會影響結果。
改動為上面代碼后,效果仍然不理想,耗時為50分鐘。
第三次優化
想了很久,第二次優化效果效果不理想的原因,其實是在左關聯中,雖然設置了左表關聯字段為空不去關聯右表,但是這樣做,左表中未關聯的記錄(ext_field7為空)將會全部聚集在一個reduce中進行處理,體現為reduce進度長時間處在99%。
換一種思路,解決辦法的突破點就在于如何把左表的未關聯記錄的key盡可能打散,因此可以這么做:若左表關聯字段無效(為空、字段長度為零、字段填充了非整數),則在關聯前將左表關聯字段設置為一個隨機數,再去關聯右表,這么做的目的是即使是左表的未關聯記錄,它的key也分布得十分均勻
?
[SQL]?純文本查看?復制代碼
?
| 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 ) |
第三次改動后,耗時從50分鐘降為了1分鐘32秒,效果顯著!
?
總結