您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“Hive中的count(distinct)如何優化”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“Hive中的count(distinct)如何優化”這篇文章吧。
COUNT(DISTINCT xxx)在hive中很容易造成數據傾斜。針對這一情況,網上已有很多優化方法,這里不再贅述。
但有時,“數據傾斜”又幾乎是必然的。我們來舉個例子:
假設表detail_sdk_session中記錄了訪問某網站M的客戶端會話信息,即:如果用戶A打開app客戶端,則會產生一條會話信息記錄在該表中,該表的粒度為“一次”會話,其中每次會話都記錄了用戶的唯一標示uuid,uuid是一個很長的字符串,假定其長度為64位。現在的需求是:每天統計當月的活用用戶數——“月活躍用戶數”(當月訪問過app就為活躍用戶)。我們以2016年1月為例進行說明,now表示當前日期。
最簡單的方法
這個問題邏輯上很簡單,SQL也很容易寫出來,例如:
SELECT COUNT(DISTINCT uuid)FROM detail_sdk_session tWHERE t.date >= '2016-01-01' AND t.date <= now
上述SQL代碼中,now表示當天的日期。很容易想到,越接近月末,上面的統計的數據量就會越大。更重要的是,在這種情況下,“數據傾斜”是必然的,因為只有一個reducer在進行COUNT(DISTINCT uuid)的計算,所有的數據都流向唯一的一個reducer,不傾斜才怪。
其實,在COUNT(DISTINCT xxx)的時候,我們可以采用“分治”的思想來解決。對于上面的例子,首先我們按照uuid的前n位進行GROUP BY,并做COUNT(DISTINCT )操作,然后再對所有的COUNT(DISTINCT)結果進行求和。
我們先把SQL寫出來,然后再做分析。
-- 外層SELECT求和SELECT SUM(mau_part) mauFROM( -- 內層SELECT分別進行COUNT(DISTINCT)計算 SELECT substr(uuid, 1, 3) uuid_part, COUNT(DISTINCT substr(uuid, 4)) AS mau_part FROM detail_sdk_session WHERE partition_date >= '2016-01-01' AND partition_date <= now GROUP BY substr(uuid, 1, 3)) t;
上述SQL中,內層SELECT根據uuid的前3位進行GROUP BY,并計算相應的活躍用戶數COUNT(DISTINCT),外層SELECT求和,得到最終的月活躍用戶數。
這種方法的好處在于,在不同的reducer各自進行COUNT(DISTINCT)計算,充分發揮hadoop的優勢,然后進行求和。
注意,上面SQL中,n設為3,不應過大。
為什么n不應該太大呢?我們假定uuid是由字母和數字組成的:大寫字母、小寫字母和數字,字符總數為26+26+10=62。理論上,內層SELECT進行GROUP BY時,會有 62^n 個分組,外層SELECT就會進行 62^n 次求和。所以n不宜過大。當然,如果數據量十分巨大,n必須充分大,才能保證內層SELECT中的COUNT(DISTINCT)能夠計算出來,此時可以再嵌套一層SELECT,這里不再贅述。
其實,很多博客中都記錄了使用GROUP BY 操作代替 COUNT(DISTINCT) 操作,但有時僅僅使用GROUP BY操作還不夠,還需要加點小技巧。
還是先來看一下代碼:
-- 第三層SELECTSELECT SUM(s.mau_part) mauFROM( -- 第二層SELECT SELECT tag, COUNT(*) mau_part FROM ( -- 第一層SELECT SELECT uuid, CAST(RAND() * 100 AS BIGINT) tag -- 為去重后的uuid打上標記,標記為:0-100之間的整數。 FROM detail_sdk_session WHERE partition_date >= '2016-01-01' AND partition_date <= now GROUP BY uuid -- 通過GROUP BY,保證去重 ) t GROUP BY tag) s;
以上是“Hive中的count(distinct)如何優化”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。