hive distinct優化
阿新 • • 發佈:2019-01-26
hive針對count(distinct xxx)只產生一個reduce的優化。
0x00 造成的原因
由於使用了distinct,導致在map端的combine無法合併重複資料;對於這種count()全聚合操作時,即使設定了reduce task個數,set mapred.reduce.tasks=100;hive也只會啟動一個reducer。這就造成了所有map端傳來的資料都在一個tasks中執行,成為了效能瓶頸。
0x01 解決方式一(分治法)
該方法優勢在於使用不同的reducer各自進行COUNT(DISTINCT)計算,充分發揮hadoop的優勢,然後進行求和,間接達到了效果。需要注意的是多個tasks同時計算產生重複值的問題,所以分組需要使用到目標列的子串。
SELECT
SUM(tmp_num) total
FROM
(select
substr(uid,1,4) tag,
count(distinct substr(uid,5)) tmp_total
from
xxtable
group by
substr(uid,1,4)
)t1
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
經過驗證,該方法在5000萬資料量的情況下,不優化需要5分鐘,經過優化需要3分鐘,還是有一定的提升的。
0x10 解決方式二(隨機分組法)
核心是使用group by替代count(distinct)。
SELECT--3
SUM(tc)
FROM
(select--2
count(*) tc,
tag
from
(select--1
cast(rand() * 100 as bigint) tag,
user_id
from
xxtable
group by
user_id
)t1
group by
tag
)t2;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1層使用隨機數作為分組依據,同時使用group by
保證去重
。 - 2層統計各分組下的統計數。
- 3層對分組結果求和。
經過驗證,該方法在5000萬資料量的情況下,不優化需要5分鐘,經過優化需要2.5分鐘,有進一步提升。