Hive求topN

  • Post author:
  • Post category:其他


select t2.* from(
    select pid,uid,cnt,row_number() over (partition by pid order by cnt desc ) as rank from 
        (
            select pid,uid,count(uid) as cnt from visit2 group by pid,uid order by pid,cnt desc
        ) as t1
    ) as t2
where t2.rank <= 3;

相关函数


)Rank


(1)RANK


() 排序相同时会重复,总数不会变


(2)DENSE_RANK


() 排序相同时会重复,总数会减少


(3)ROW_NUMBER


() 会根据顺序计算


2)


OVER():指定分析函数工作的数据窗口大小,这个数据窗口大小可能会随着行的变而变化


(1)


CURRENT ROW:当前行


(2)


n PRECEDING:往前n行数据


(3)


n FOLLOWING:往后n行数据


(4)


UNBOUNDED:起点,UNBOUNDED PRECEDING 表示从前面的起点, UNBOUNDED FOLLOWING表示到后面的终点


(5)


LAG(col,n):往前第n行数据


(6)


LEAD(col,n):往后第n行数据


(7)


NTILE(n):把有序分区中的行分发到指定数据的组中,各个组有编号,编号从1开始,对于每一行,NTILE返回此行所属的组的编号。注意:n必须为int类型。

group by & partition by & Distribute by

group by分组之后是会组内聚合的而后两者仅仅是分组了,并未有聚合操作

partition by 是分区 distribute by 可以理解为分簇

partition by 区内排序用 order by,  distribute by 簇内排序用sort by

另外当 distribute by 和 sorts by 后的字段相同时,可以使用 cluster by 方式

partitioned by (分区名 string) 按所分区名分区建表使用

clustered by(列名)  按列分桶建表使用

order by

order by 会对数据进行全局排序,和oracle和mysql等数据库中的order by 效果一样,它只在一个 reduce 中进行所以数据量特别大的时候

效率非常低

distribute by

DISTRIBUTE BY 是控制在map端

如何拆分数据给 reduce 端

的。hive会根据 distribute by后面列,对应 reduc e的个数进行分发,默认是采用 hash 算法。

sort by

sort by

为每个reduce产生一个排序文件

。在有些情况下,你需要控制某个特定行应该到哪个reducer,这通常是为了进行后续的聚集操作。distribute by刚好可以做这件事。因此,distribute by经常和sort by配合使用。

group by

和distribute by类似 都是按key值划分数据 都使用 reduce 操作

唯一不同的是,distribute by只是单纯的

分散数据

,distribute by col – 按照col列把数据分散到不同的reduce。

而group by把相同key的数据

聚集到一起



后续必须是聚合操作

cluster by

distribute by 和 sort by 合用就相当于cluster by,但是cluster by 不能指定排序为asc或 desc 的规则,只能是升序排列。

partition by

通常查询时会对整个数据库查询,而这带来了大量的开销,因此引入了partition的概念,在建表的时候通过设置partition的字段, 会根据该字段对数据分区存放,更具体的说是存放在不同的文件夹,这样通过指定设置Partition的字段条件查询时可以减少大量的开销

优化

也可以使用Hive提供的limit关键字,再配合 order by 实现 SELECT TOP N 很方便

但是 Hive 中 order by 只使用1个 reduce,如果表的数据量很大,那么 order by 就会力不从心

例如:select a from test01 order by a limit 10;

控制台会打印出:Number of reduce tasks determined at compile time: 1

说明启动的 reduce 数量是编译时确定的。

查看该 SQL 的执行计划,该 SQL 只启动1个JOB。

假设数据表有1亿条数据,而我们只想取TOP 10,那对1亿条数据在1个 reduce 中做全排序非常不合理

幸好有sort by,使用 sort by 替换 order by 就可以解决这个问题:

select a from test01 sort by a limit 10;

首先执行该 SQL 控制台打印出:Number of reduce tasks not specified. Estimated from input data size: 1

说明 reduce 数不是编译时确定的,而是根据输入文件大小动态确定的。

sort by 可以启动多个 reduce,每个 reduce 做局部排序,但是这对于 sort by limit N 已经够用了。从执行计划中可以看出 sort by limit N 启动了两个JOB。第一个 JOB 是在每个 reduce 中做局部排序,然后分别取 TOP N。假设启动了 M 个 reduce,第二个 JOB 再对 M 个 reduce 分别局部排好序的总计 M * N 条数据做全局排序,取 TOP N,从而得到想要的结果。这样就可以大大提高 SELECT TOP N 的效率。

distribute By: 在有些情况下,我们需要控制某个特定行应该到哪个 reducer,通常是为了进行后续的聚集操作。

distribute by

子句可以做这件事。

distribute by

类似 MR 中partition(自定义分区),进行分区,结合sort by使用。

对于 distribute by 进行测试,一定要分配多 reduce 进行处理,否则无法看到 distribute by 的效果。

注意:

1.distribute by 的分区规则是根据分区字段的 hash 码与 reduce 的个数进行模除后,余数相同的分到一个区。

2.Hive要求 distribute by 语句要写在 sort by 语句之前。



版权声明:本文为a308601801原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。