一.數據傾斜
? ? 在計算數據的時候,數據的分散度不夠,導致大量的數據集中到了一臺或者幾臺機器上計算,這些數據的計算速度遠遠低于平均計算速度,導致整個計算過程過慢。
? 如何解決
? ? ? ?訂單場景,某一天在北京和上海兩個城市多了強力的推廣,結果可能是這兩個城市的訂單量增長了10000%,其余城市的數據量不變。然后我們要統計不同城市的訂單情況,這樣,一做group操作,可能直接就數據傾斜了。
解決數據傾斜有這幾個思路:
1.業務邏輯,上面的例子,我們單獨對這兩個城市來做count,最后和其它城市做整合。
2.程序層面,Hive中,經常遇到count(distinct)操作,這樣會導致最終只有一個reduce,可以先group 再在外面包一層count。
3.調參方面,Hadoop和Spark都自帶了很多的參數和機制來調節數據傾斜,合理利用它們就能解決大部分問題。
? ? ? ? ? ? ? ? ? set hive.exec.reducers.max=200;
? ? ? ? ? ? ? ? ? set mapred.reduce.tasks= 200;---增大Reduce個數
? ? ? ? ? ? ? ? ? set hive.groupby.mapaggr.checkinterval=100000 ;--group的鍵對應的記錄條數超過這個值則會進行分拆,值根據具體數據量設置
? ? ? ? ? ? ? ? ? set hive.groupby.skewindata=true; --如果是group by過程出現傾斜 應該設置為true
? ? ? ? ? ? ? ? ? set hive.skewjoin.key=100000; --這個是join的鍵對應的記錄條數超過這個值則會進行分拆,值根據具體數據量設置
? ? ? ? ? ? ? ? ? set hive.optimize.skewjoin=true;--如果是join 過程出現傾斜 應該設置為true
? ?從業務和數據上解決數據傾斜 :
有損的方法:
找到異常數據,比如ip為0的數據,過濾掉
無損的方法:
對分布不均勻的數據,單獨計算
先對key做一層hash,先將數據打散讓它的并行度變大,再匯集
數據預處理
二.常用函數
1.FIRST_VALUE
? ?取分組內排序后,截止到當前行,第一個值
2.LAST_VALUE
? ?取分組內排序后,截止到當前行,最后一個值
? ? ? 用法:
?? ? ? first_value(testtype) over (partition by device_id order by create_time desc) as testtype
3.lateral view explode
? ?lateral view用于和split、explode等UDTF一起使用的,能將一行數據拆分成多行數據,在此基礎上可以對拆分的數據進行聚合,lateral view首先為原始表的每行調用UDTF,UDTF會把一行拆分? ? ?成一行或者多行,lateral view在把結果組合,產生一個支持別名表的虛擬表。
A???????????????????????? B??????????????????????????????? C
190???? [1030,1031,1032,1033,1190]????? select id
191???? [1030,1031,1032,1033,1190]????? select id
希望的結果是:
190??? 1030? select id?
190??? 1031? select id
190??? 1032? select id?
190??? 1033? select id
190??? 1190? select id
191??? 1030? select id
191??? 1031? select id
191??? 1032? select id?
191??? 1033? select id
191??? 1190? select id
select?A,B,C from table_1 LATERAL VIEW explode(B) table1 as B得到上述結果
4.字符串連接函數:concat?
? ?語法: concat(string A, string B…)
? ?返回值: string
? ?說明:返回輸入字符串連接后的結果,支持任意個輸入字符串
舉例:?
? ?hive> select concat(‘abc’,'def’,'gh’) from lxw_dual;
? ?abcdefgh
5.帶分隔符字符串連接函數:concat_ws
? ?語法:?concat_ws(string?SEP,?string?A,?string?B…)??
? ?返回值:?string??
? ?說明:返回輸入字符串連接后的結果,SEP表示各個字符串間的分隔符??
? ?舉例:??
?? ?hive>?select?concat_ws(‘,’,'abc’,'def’,'gh’)?from?dual;??
? ?abc,def,gh??
6.collect_max
語法:FUNC(x,val,n)其中n是要返回的值的數量,val為double類型。
? ?說明:Similar to collect, but save only the keys containing the max 20 values.?
???舉例 :collect_max(coalesce(receiver_mobile, ''), cast(mobile_cnt as double), 3)
? ? ?返回三個 map
7.map_keys
? ?語法:map_keys(Map)
? ?返回值:Returns an unordered array containing the keys of the input map.
? ?說明:
? ?舉例:map_keys(collect_max(coalesce(receiver_mobile, ''), cast(mobile_cnt as double), 3))
8.map_values
? ?語法:map_values(Map)
? ?返回值:Returns an unordered array containing the values of the input map.
? ?說明:
9.unix_timestamp
? ?獲取當前UNIX時間戳函數:?unix_timestamp
? ?語法:???unix_timestamp()
返回值:???bigint?
說明:?獲得當前時區的UNIX時間戳?
? ?舉例:
?hive>???select?unix_timestamp()?from?dual;
1323309615?
? ?日期轉UNIX時間戳函數:?unix_timestamp
? ?語法:???unix_timestamp(string?date)
返回值:???bigint?
? ?說明:?轉換格式為“yyyy-MM-dd?HH:mm:ss“的日期到UNIX時間戳。如果轉化失敗,則返回0。
? ?舉例:
hive>???select?unix_timestamp(’2011-12-07?13:01:03′)?from?dual;?
? ?1323234063
? ?指定格式日期轉UNIX時間戳函數:?unix_timestamp
? ?語法:???unix_timestamp(string?date,?string?pattern)
? ?返回值:???bigint
? ?說明:?轉換pattern格式的日期到UNIX時間戳。如果轉化失敗,則返回0。
? ?舉例:
? ?hive>???select?unix_timestamp(’20111207?13:01:03′,’yyyyMMdd?HH:mm:ss’)?from?dual;
? ?1323234063
9.lag,lead
lag 和lead 可以 獲取結果集中,按一定排序所排列的當前行的上下相鄰若干offset 的某個行的某個列(不用結果集的自關聯);lag ,lead 分別是向前,向后
語法:LAG(col,n,DEFAULT)?
說明:用于統計窗口內往上第n行值,第一個參數為列名,第二個參數為往上第n行(可選,默認為1),第三個參數為默認值(當往上第n行為NULL時候,取默認值,如不指定,則為NULL)
? ? 返回值:見說明
? ? 舉例:
HIve> select * ?from kkk; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ID NAME ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
---------- -------------------- ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ?1 1name ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ?2 2name ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ?3 3name ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ?4 4name ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ?5 5name ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
HIve> select id,name,lag(name,1,0) over ( order by id ) ?from kkk;?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ID NAME ? ? ? ? ? ? ? ? LAG(NAME,1,0)OVER(ORDERBYID) ? ? ?
---------- -------------------- ---------------------------- ? ? ?
? ? ? ? ?1 1name ? ? ? ? ? ? ? ?0 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ?2 2name ? ? ? ? ? ? ? ?1name ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ?3 3name ? ? ? ? ? ? ? ?2name ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ?4 4name ? ? ? ? ? ? ? ?3name ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ?5 5name ? ? ? ? ? ? ? ?4name ? ? ? ? ? ? ? ? ? ? ? ? ? ??? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
HIve> select id,name,lead(name,2,0) over ( order by id ) ?from kkk;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ID NAME ? ? ? ? ? ? ? ? LEAD(NAME,2,0)OVER(ORDERBYID) ? ??
---------- -------------------- ----------------------------- ? ??
? ? ? ? ?1 1name? ? ? ? ? ? ? ? 3name ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ?2 2name? ? ? ? ? ? ? ? 4name ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ?3 3name? ? ? ? ? ? ? ? 5name ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ?4 4name ? ? ? ? ? ? ? ?0? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ?5 5name ? ? ? ? ? ? ? ?0 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
10.GROUPING SETS
? ? ? ? GROUPING SETS會把在單個GROUP BY邏輯中沒有參與GROUP BY的那一列置為NULL值,使它成為常量占位列。這樣聚合出來的結果,未被GROUP BY的列將顯示為NULL。但是數據表中很可能原來存在NULL值,所以會有歧義,為了解決這個歧義問題,可以使用HQL提供的一個Grouping__ID函數,這個函數沒有參數,在有GROUPING SETS子句的情況下,把它直接放在SELECT子句中,獨占一列。它返回的結果是一個看起來像整形數值類型,其實是字符串的值,這個值使用了位圖策略(bitvector,位向量),即它的二進制形式中的每1位標示著對應列是否參與GROUP BY,如果某一列參與了GROUP BY,對應位就被置為1,否則為0,根據這個位向量值和對應列是否顯示為NULL,就可以解決上面提到的歧義問題了。
11.get_json_object(string json_string, string path)
語法:get_json_object(ctx,'$.category_name') p.s加$.符號
? ? 返回值:?string??
? ? 說明:解析json的字符串json_string,返回path指定的內容。如果輸入的json字符串無效,那么返回NULL。??
? ? 類比:
? ? parse_url(‘http://facebook.com/path/p1.php?query=1‘, ‘HOST’)返回’facebook.com’ ,
? ? parse_url(‘http://facebook.com/path/p1.php?query=1‘, ‘PATH’)返回’/path/p1.php’ ,?
? ? parse_url(‘http://facebook.com/path/p1.php?query=1‘, ‘QUERY’)返回’query=1’,?
12.日期增加函數 date_add(start_date, num_days)
返回類型:string
描述:返回增加num_days 天數的日期(負數則為減少)
date_add(start_date, num_days) - Returns the date that is num_days after start_date.
舉例:
hive>select date_add('2014-09-16 15:50:08.119',10) from default.dual;
2014-09-26
hive>select date_add('2014-09-16 15:50:08.119',-10) from default.dual;
2014-09-06
13.日期減少函數 date_sub(start_date, num_days)
返回類型:string
描述:返回num_days 天數之前的日期(負數則為增加)
date_sub(start_date, num_days) - Returns the date that is num_days before start_date.
舉例:
hive>select date_sub('2014-09-16 15:50:08.119',10) from default.dual;
2014-09-06
hive>select date_sub('2014-09-16 15:50:08.119',-10) from default.dual;
2014-09-26
三.查詢優化
1.join前把不必要的數據濾掉,on字句不要加多余的判斷(盡量盡早的過濾數據,減少每個階段的數據量)
? ?(tb13.test_device_id=tb3.imei?and tb3.device_id!='')
2.對于連續的數值,能用 between 就不要用 in?
?? ?select id from t where num in(1,2,3)
? ?select id from t where num between 1 and 3
3.jion操作 ?
? ?小表要注意放在join的左邊
? ?否則會引起磁盤和內存的大量消耗
4.not in
? select a.key from a left outer join b on a.key=b.key where b.key is null
5. 使用相同的連接鍵
? ?當對3個或者更多個表進行join連接時,如果每個on子句都使用相同的連接鍵的話,那么只會產生一個MapReduce job。