Hive个人笔记

一.数据倾斜

    在计算数据的时候,数据的分散度不够,导致大量的数据集中到了一台或者几台机器上计算,这些数据的计算速度远远低于平均计算速度,导致整个计算过程过慢。


  如何解决

       订单场景,某一天在北京和上海两个城市多了强力的推广,结果可能是这两个城市的订单量增长了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。

你可能感兴趣的:(Hive个人笔记)