使用者軌跡工程的效能瓶頸一直是etract_track_info,其中耗時大戶主要在於trackinfo與pm_info進行左關聯的環節,trackinfo與pm_info兩張表均為gb級別,左關聯**塊如下:
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裡面,因此,改為如下:
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為無效字段,則不需要關聯,因此,改為如下:
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也分布得十分均勻
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秒,效果顯著! hive大表join空key優化
假如不需要id為null的資料!此時可以將a表中id為null的字段提前過濾,減少mr在執行時,輸入的資料量!解決 將null值過濾,過濾後再執行join select from a where c is not null a left join b on a.c b.ca表中c欄位為null的資料...
Hive中小表與大表關聯 join 的效能分析
經常看到一些hive優化的建議中說當小表與大表做關聯時,把小表寫在前面,這樣可以使hive的關聯速度更快,提到的原因都是說因為小表可以先放到記憶體中,然後大表的每條記錄再去記憶體中檢測,最終完成關聯查詢。這樣的原因看似合理,但是仔細推敲,又站不住腳跟。多小的表算小表?如果所謂的小表在記憶體中放不下怎...
Hive中小表與大表關聯 join 的效能分析
經常看到一些hive優化的建議中說當小表與大表做關聯時,把小表寫在前面,這樣可以使hive的關聯速度更快,提到的原因都是說因為小表可以先放到記憶體中,然後大表的每條記錄再去記憶體中檢測,最終完成關聯查詢。這樣的原因看似合理,但是仔細推敲,又站不住腳跟。多小的表算小表?如果所謂的小表在記憶體中放不下怎...