hive-7 Hive高级查询之group-by

Group-by

  • 用处
  • Group by语法
    • 示例
  • 注意
  • 高级特性:Multi-Group-By Inserts
  • group by 优化

用处

  • group by经常和聚合函数一起使用,按照一个活多个列对结果进行分组,然后对每个组进行聚合操作。

Group by语法

groupByClause: GROUP BY groupByExpression (, groupByExpression)*
groupByExpression: expression
groupByQuery: SELECT expression (, expression)* FROM src groupByClause?

示例

  • 根据性别,计算去重用户数
  INSERT OVERWRITE TABLE pv_gender_sum
  SELECT pv_users.gender, count (DISTINCT pv_users.userid)
  FROM pv_users
  GROUP BY pv_users.gender;

注意

  • 使用group by时,select语句只能包含group by的列和聚合函数
# 合法
SELECT
   a,
   sum(b)
FROM
   t1
GROUP BY
   a;
# 非法,select中含有b,而group by中没有b
SELECT
   a,
   b
FROM
   t1
GROUP BY
   a;
  • 可以做多个聚合操作,但是,不能有两个聚合操作有不同的distinct
# 合法:count(DISTINCT) and sum(DISTINCT) 指定了相同的列
INSERT OVERWRITE TABLE pv_gender_agg
SELECT pv_users.gender, count(DISTINCT pv_users.userid), 
count(*), sum(DISTINCT pv_users.userid)
FROM pv_users
GROUP BY pv_users.gender;
# 非法:DISTINCT 指定了两个不同的列:userid、ip
INSERT OVERWRITE TABLE pv_gender_agg
SELECT pv_users.gender, count(DISTINCT pv_users.userid), count(DISTINCT pv_users.ip)
FROM pv_users
GROUP BY pv_users.gender;

高级特性:Multi-Group-By Inserts

简单查询或者聚合的输出,可以发送到多个表甚至是hadoopdfs文件(可以使用hdfs工具管理)。

  • 分别按照年龄和性别分组,求出每组去重后的用户数量,去往不同的地方(表和HDFS)
# 注意分号,下面这是一个SQL语句
FROM pv_users 
  INSERT OVERWRITE TABLE pv_gender_sum
    SELECT pv_users.gender, count(DISTINCT pv_users.userid) 
    GROUP BY pv_users.gender 
  INSERT OVERWRITE DIRECTORY '/user/facebook/tmp/pv_age_sum'
    SELECT pv_users.age, count(DISTINCT pv_users.userid) 
    GROUP BY pv_users.age; 

group by 优化

  • Map端先进行部分聚合:不是所有的聚合操作都需要在reduce端进行,先在map端进行聚合操作可以减少网络传输。(需要在map端占据更多的内存

    • 开启Map端聚合操作
      #默认为true
      set hive.map.aggr = true;
      
    • 设置Map端进行聚合操作的条目数目
        set hive.groupby.mapaggr.checkinterval = 100000;
      
  • 有数据倾斜时,进行负载均衡 :默认情况下,Map阶段同一Key数据分发给一个reduce,当一个key数据过大时就倾斜了。

    hive.groupby.skewindata = true
    
  • 当选项设定为 true,生成的查询计划会有两个MR Job。第一个MR Job中,Map的输出结果会随机分布到Reduce中,每个Reduce做部分聚合操作,并输出结果,这样处理的结果是相同的Group By Key有可能被分发到不同的Reduce中,从而达到负载均衡的目的;第二个MR Job再根据预处理的数据结果按照Group By Key分布到Reduce中(这个过程可以保证相同的Group By Key被分布到同一个Reduce中),最后完成最终的聚合操作。

  • 增加reduceTask数量: group by使用了reduce操作,效率受限于reduceTask数量,设置reduceTask数量可以提高效率(用的比较少)

set mapred.reduce.tasks=3;
select userid,count(1) as num from pv_usersgroup by userid;

官网链接

你可能感兴趣的:(Hive)