此篇文章是總結實際業務中遇到的計算場景問題。
hive 參數調優的文章很多,此篇文章不做類似方面的描述。
文章描述在數據統計場景中,可以通過hive 一些函數的組合使用,極大提高計算效率的方式。
選擇一張表中的不同字段值轉化為列
演示場景描述:
業務表表 A :
table A ( id int, create_date bigint )
日志表 B :
table B ( id int, type string, lat double, lng double )
type 的取值為 'type_1','type_2','type_3'。
希望最終得到結果
table C( id int, create_date, type_1_lat, type_1_lng, type_2_lat, type_2_lng, type_3_lat, type_4_lng )
type_1_lat 表示為type_1值時的lat值
方法一:
select a.*, b1.lat, b1.lng, b2.lat, b2.lng, b3.lat, b3.lng from A a left join ( select * from B where type = 'type_1' ) b1 on a.id = b1.id left join ( select * from B where type = 'type_2' ) b2 on a.id = b2.id left join ( select * from B where type = 'type_1' ) b3 on a.id = b3.id
這確實不失為一個方案,可是我們思考一下,如果type_N的、在日志表數據量很大的情況,不停的執行left join,在分布式計算中還是會存在大量的shuffle操作,執行效率會越來越低。
即使使用hive參數優化,不改變大量left join 的情況下,這樣的優化空間也是有限的。
換個思路,方法二:
with c as ( select a.*, if(b.type = 'type_1',b.lat,'') as type_1_lat, if(b.type = 'type_1',b.lng,'') as type_1_lng, if(b.type = 'type_2',b.lat,'') as type_2_lat, if(b.type = 'type_2',b.lng,'') as type_2_lng, if(b.type = 'type_3',b.lat,'') as type_3_lat, if(b.type = 'type_3',b.lng,'') as type_3_lng from A a left join B b on a.id = b.id ) select id, concat_ws('',collect_list(type_1_lat)) as type_1_lat, concat_ws('',collect_list(type_1_lng)) as type_1_lng, concat_ws('',collect_list(type_2_lat)) as type_2_lat, concat_ws('',collect_list(type_2_lng)) as type_2_lng, concat_ws('',collect_list(type_3_lat)) as type_3_lat, concat_ws('',collect_list(type_3_lng)) as type_3_lng from c group by id
講一下思路,這是一個有點巧的辦法。
以 type_1_lat 舉例子。
第一步相當於把兩個表全部做左連接,但是在type_1上有值的那一行,其他的所有列一定是沒有值的,采用空字符串進行代替。
第二部按照id進行聚合操作,兩個函數分別操作的含義可以解釋為,先將type_1_lat列合並為一個集合,此時這一列的集合里面,只有一個值,其他的都為空字符串,
然后將所有值在用空字符串進行拼接,最后得到的結果,仍然是type_1_lat的值。其他的列是同樣的道理。
煩請指正~