1. 程式人生 > >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 t
WHERE t.date >= '2016-01-01' AND t.date <= now
  • 1
  • 2
  • 3
  • 4

上述SQL程式碼中,now表示當天的日期。很容易想到,越接近月末,上面的統計的資料量就會越大。更重要的是,在這種情況下,“資料傾斜”是必然的,因為只有一個reducer在進行COUNT(DISTINCT uuid)的計算,所有的資料都流向唯一的一個reducer,不傾斜才怪。

優化1

其實,在COUNT(DISTINCT xxx)的時候,我們可以採用“分治”的思想來解決。對於上面的例子,首先我們按照uuid的前n位進行GROUP BY,並做COUNT(DISTINCT )操作,然後再對所有的COUNT(DISTINCT)結果進行求和。 
我們先把SQL寫出來,然後再做分析。

-- 外層SELECT求和
SELECT
  SUM(mau_part) mau
FROM
(
  -- 內層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,這裡不再贅述。

優化2

其實,很多部落格中都記錄了使用GROUP BY 操作代替 COUNT(DISTINCT) 操作,但有時僅僅使用GROUP BY操作還不夠,還需要加點小技巧。 
還是先來看一下程式碼:

--  第三層SELECT
SELECT
  SUM(s.mau_part) mau
FROM
(
  -- 第二層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
;
  1. 第一層SELECT:對uuid進行去重,併為去重後的uuid打上整數標記
  2. 第二層SELECT:按照標記進行分組,統計每個分組下uuid的個數
  3. 第三層SELECT:對所有分組進行求和 
    上面這個方法最關鍵的是為每個uuid進行標記,這樣就可以對其進行分組,分別計數,最後去和。如果資料量確實很大,也可以增加分組的個數。例如:CAST(RAND() * 1000 AS BIGINT) tag 
    —-EOF—– 
    Categories: hive Tags: hive COUNT DISTINCT

相關推薦

Hivecount(distinct)優化

問題描述 COUNT(DISTINCT xxx)在hive中很容易造成資料傾斜。針對這一情況,網上已有很多優化方法,這裡不再贅述。  但有時,“資料傾斜”又幾乎是必然的。我們來舉個例子: 假設表detail_sdk_session中記錄了訪問某網站M的客戶端會話資訊,即:

Postgresql資料庫count(distinct)優化

基本資訊 基本情況 表共800W資料,從260W的結果集中計算出不同的案件數量(130萬),需要執行20多秒 原SQL內容 select count(distinct c_bh_aj) as ajcount from db_znspgl.

#hive#hiveDistinct,group by

Select一些資料時候,會做一些去重處理,比如通過distinct 和group by來去重。 (1)distinct distinct,在資料量不大的情況下,我都會用,主要自己懶的寫group by  xxx這麼多的欄位,額。當資料量太大時候,特別是count(dist

mysqlcount(*),distinct的使用方法和效率研究

SQL 語句的COUNT有兩種用途 1. 用來計算行數——Count(*) 2. 用來計算某個值的數量——COUNT(col1) Count(*) 永遠返回的都是結果集中的行數,而COUNT(col1)只返回col1值非空的記錄數,如果col1值全部非空, Count(*)和COUNT(col1)的結果是相同

Hivecount,sum的使用

目錄 1.簡介 2.count,sum使用區別 3.實操 1.簡介 在日常的工作中,總避免不了統計總數,Hive中常用的統計有兩個函式 count sum 可以在count,sum中裡使用case when、distinct等處理,滿足日常資料統計需求。

hive優化-count(distinct)

問題描述 COUNT(DISTINCT xxx)在hive中很容易造成資料傾斜。針對這一情況,網上已有很多優化方法,這裡不再贅述。 但有時,“資料傾斜”又幾乎是必然

Hive SQL優化Count Distinct

Hive是Hadoop的子專案,它提供了對資料的結構化管理和類SQL語言的查詢功能。SQL的互動方式極大程度地降低了Hadoop生態環境中資料處理的門檻,使用者不需要編寫程式,通過SQL語句就可以對資料進行分析和處理。目前很多計算需求都可以由Hive來完成,極大程度地降低

在Apache Kylin使用Count Distinct

雷頓學院大資料:http://www.leidun.site/ 在OLAP多維分析中,Count Distinct(去重計數)是一種非常常用的指標度量,比如一段時間內的UV、活躍使用者數等等;從1.5.3開始,Apache Kylin提供了兩種Count Distinct計算方式,一種是近

關於hivecount與group by的總結

Group By語句從英文的字面意義上理解就是“根據(by)一定的規則進行分組(Group)”。它的作用是通過一定的規則將一個數據集劃分成若干個小的區域,然後針對若干個小區域進行資料處理。  注意:group by 是先排序後分組;  count :. 1、 並不是說

sql語句count(distinct column)問題記錄

閒話不多說,直接上乾貨。老帖們,切記不要隨意copy!copy有風險,發帖須謹慎! 按照慣性思維,統計一個欄位去重後的條數我們的sql寫起來如下: select count(distinct column)from db.table 如果colu

Hive的去重 :distinct,group by與ROW_Number()視窗函式

一、distinct,group by與ROW_Number()視窗函式使用方法 1. Distinct用法:對select 後面所有欄位去重,並不能只對一列去重。 (1)當distinct應用到多個欄位的時候,distinct必須放在開頭,其應用的範圍是其後面的所有欄位,而不只是緊挨著它的一個欄位,而且di

Hive資料壓縮(企業優化

二 、配置mapreduce和hive中使用snappy壓縮         將snappy解壓,將Lib下的native複製到hadoop下的lib   1、 實際就是對mapreduce過程中

hivedistinct用法

hive中的distinct是去重的意思,和group by在某些情況下有相同的功能 下面測試下distinct的部分功能,先建立一張測試表 create table test.trip_tmp( id int, user_id int, salesman_id int, huose

hiveselectDISTINCT的技巧和使用

以下是轉載內容 單表的唯一查詢用:distinct 多表的唯一查詢用:group by 在使用MySQL時,有時需要查詢出某個欄位不重複的記錄,雖然mysql提供有distinct這個關鍵字來過濾掉多餘的重複記錄只保留一條,但往往只用它來返回不重複記錄的條數,而不是用它來返

sqlcount函式和distinct函式的配合使用

使用者名稱    商品    數量 A        甲      1 B        乙      2 C        丙      2 B        甲      1 A        丙      2 C        丙      1 寫sql語句 要求查出

Hivedistinct和Group by效率對比及處理方式

select res.flag AS flag ,res.source AS source ,res.template AS template ,SUM(res.click_user)

hive count distinct

select count(distinct user_id) from dm_user where ds=20150701; 使用disticnt函式,所有的資料只會shuffle到一個reducer上,導致reducer資料傾斜嚴重 優化後為 set mapred.red

hive distinct優化

hive針對count(distinct xxx)只產生一個reduce的優化。0x00 造成的原因由於使用了distinct,導致在map端的combine無法合併重複資料;對於這種count()全聚合操作時,即使設定了reduce task個數,set mapred.reduce.tasks=100;hi

hive與hbase外部表join時記憶體溢位(hive處理mapjoin的優化器機制)

與hbase外部表(wizad_mdm_main)進行join出現問題: CREATE TABLE wizad_mdm_dev_lmj_edition_result as select *  from  wizad_mdm_dev_lmj_20141120 as w JOI

sql優化之:count(distinct xxxx)

select count(distinct   column) from table_name; 這樣一條sql在資料量比較大時可能跑的時間很長。 可以用:select count(1) from (select   column from table_name group