搜索
首页数据库mysql教程Hive.分组排序和TOP

Hive.分组排序和TOP

Jun 07, 2016 pm 03:55 PM
hqlsqltop分组排序查询

HQL作为类SQL的查询分析语言,到目前为止,应该也还未能达到其它流行的SQL(如Transact-SQL, MySQL)实现那样完善。而在公司的生产环境中,我想应该也不会紧贴Hive版本更新的步伐,始终部署最新版的Hive;可能会滞后一两个大版本神马的;毕竟,虽然开源工具

HQL作为类SQL的查询分析语言,到目前为止,应该也还未能达到其它流行的SQL(如Transact-SQL, MySQL)实现那样完善。而在公司的生产环境中,我想应该也不会紧贴Hive版本更新的步伐,始终部署最新版的Hive;可能会滞后一两个大版本神马的;毕竟,虽然开源工具的透明性是一大利好,但与闭源的商业工具相比,在可用性等问题上的保障性还是略弱。

使用HQL进行离线分析用户数据时,就算已经过聚合处理,但我们也可能只对那些突出的量化指标或者这些指标的增量变化感兴趣,所以对聚合数据排序(按某列降序?增序?)成为很基本的需要,这在HQL这样尚未成熟的语言中,结合orderby, limit子句可以毫无鸭梨地完成。

然而,即使我们可以把多个字段放入order by子句中,并指定各个字段的升降顺序,如:

order by fieldA desc, fieldB [asc], fieldC desc
但排序操作始终是全局的,我们有时候想要的却是分组排序,即按fieldA排序以后,然后针对fieldA的每个值所对应的fieldB和(或)fieldC排序,而不是像order by那样,针对所有fieldA的值对fieldB和(或)fieldC排序。

为了满足这个需要,Transact-SQL提供了over, partition by句和 row_number()函数,而Hive也在0.11中引入over, partition by子句和rank函数,以此提供方便的窗口分析(分组分析)功能。

那对于0.11版之前的Hive,我们可以实现分组排序吗?答案是肯定的,只是看起来没那么直接。

要实现这个需求,就需要请出distribute by, sort by这两个重要角色了,distribute by能够执行我们需要的分组功能,再结合Hive查询的MapReduce Job特性,sort by又可以在分组内进行局部排序。

当然,如果只有它们,我们只能得到排序后的一堆数据,但是无法知道每一条数据的名次,这就要自己编写UDF函数,来确定和返回名次了,这个函数貌似在网络上流传甚广:

public final class Rank extends UDF {
      private int counter;
      private String last_key ="";
 
      public int evaluate(final String key) {
             if (key == null) {
                    this.last_key= "";
                    this.counter= 0;
                    return counter;
             }
             if(!key.equalsIgnoreCase(this.last_key)) {
                    this.counter= 0;
                    this.last_key= key;
             }
             return this.counter++;
      }
}

在这里我们忽略了自定义UDF的注册的环节。。。在分组之后,应用Rank函数,这个函数始终跟踪最新的参数值,在参数值连续相同的情况下,就将字段counter作自增操作并返回这个计数值;而如果出现和上一次函数调用不同的参数值,Rank函数会重置其计数值字段和key字段(对应参数值)使我们得到一个int类型的名次值。

Hive里称这个为自定义函数,实际上每个自定义函数是一个实现了evaluate方法的类,这个叫法略不福啊。

有了distribute by, sort by和这个Rank函数,我们就能够实现分组排序了,编写HQL查询脚本之前,我们还需要明确:

1. 分组字段:distribute by的字段是哪个(些)?

2. 排序依据:sort by的字段是哪个(些)?

3. 函数参数:Rank函数需要String参数,我们应该给Rank函数传递什么东西作为实参?

不晓得是因为以上这3个问题确实像我们在教科书上偶尔会看到的“容易证得”,还是因为博主们只是想了这个问题,并没有实践,反正我看到的网络上讲分组排序(TOP)的博文都没有明确地提出这3个问题。而按我的实践经历来看,初次实现这种需求的童鞋,就算看了这些博文,在得到正确结果之前,应该都会经历各种困惑,下面我们从实际的场景来看看。

比如,我们需要查询得到这样的数据:每日使用应用myAPP的UV量TOP 30的设备,和这TOP 10的设备中每个设备的流量(VV)最高的10项版块内容(以内容ID来区分);

假定查询所需的Hive表为:hiveTab_useraction

思路梗概:先用一个子查询查出来每台设备的访问内容,同时,用一个子查询查出来TOP30的设备,然后两个表做内连接(join),然后在外层查询中提取所需字段列和数据列。

在这个流程里面:

1)找出TOP10的设备这个环节看起来没有涉及分组排序,但还是需要考虑上面3个问题,因为我们要得到名次,而order by貌似不能同Rank函数友好协作(也有可能是我使用的方式不科学呢),而且,在以下呈现的脚本中,我们还生成了一个常量字符串的distribute_key;

2)然后在外层循环中更需要考虑上面3个问题。

请见HQL脚本:

select
	device_rank,
	device_info,
	vv_rank,
	pageID,	
	act_vv
from
(
	select
		device_rank,
		device_info,
		(Rank(device_rank) + 1) as vv_rank,
		pageID,
		act_vv
	from
	(	
		select
			t2.device_rank,
			t2.device_info,
			t1.pageID,
			t1.act_vv
		from
		(
			select
				fieldA as device_info,
				pageID,
				count(1) as act_vv
			from hiveTab_useraction
			where `date` >= dateStart and `date` <= dateEnd
			group by fieldA, pageID
		) t1
		join
		(
			select
				(Rank(distribute_key) + 1) as device_rank,
				device_info,
				act_uv
			from
			(
				select
					distribute_key,
					device_info,
					act_uv
				from
				(
					select
						&#39;topdevice&#39; as distribute_key,
						device_info,
						act_uv
					from
					(
						select
							fieldA as device_info,
							count(distinct uid) as act_uv
						from hiveTab_useraction
						where `date` >= dateStart and `date` <= dateEnd
						group by fieldA
					) t
					order by act_uv desc
					limit 10
				) t
				distribute by distribute_key 
				sort by act_uv desc
			) t
		) t2 on (t1.device_info = t2.device_info)
		distribute by t2.device_rank
		sort by t2.device_rank, t1.act_vv desc
	) t
) t
where vv_rank <= 10
从脚本实测来看,上面提到的需要明确的3个问题,真的很重要。另外,Rank函数返回的名次是从0开始,所以我们需要作+1处理。

Hive向普通用户也开放了自行编写、注册和使用自定义函数的功能,这一点确实带来了很大的扩展性。

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
MySQL的许可与其他数据库系统相比如何?MySQL的许可与其他数据库系统相比如何?Apr 25, 2025 am 12:26 AM

MySQL使用的是GPL许可证。1)GPL许可证允许自由使用、修改和分发MySQL,但修改后的分发需遵循GPL。2)商业许可证可避免公开修改,适合需要保密的商业应用。

您什么时候选择InnoDB而不是Myisam,反之亦然?您什么时候选择InnoDB而不是Myisam,反之亦然?Apr 25, 2025 am 12:22 AM

选择InnoDB而不是MyISAM的情况包括:1)需要事务支持,2)高并发环境,3)需要高数据一致性;反之,选择MyISAM的情况包括:1)主要是读操作,2)不需要事务支持。InnoDB适合需要高数据一致性和事务处理的应用,如电商平台,而MyISAM适合读密集型且无需事务的应用,如博客系统。

在MySQL中解释外键的目的。在MySQL中解释外键的目的。Apr 25, 2025 am 12:17 AM

在MySQL中,外键的作用是建立表与表之间的关系,确保数据的一致性和完整性。外键通过引用完整性检查和级联操作维护数据的有效性,使用时需注意性能优化和避免常见错误。

MySQL中有哪些不同类型的索引?MySQL中有哪些不同类型的索引?Apr 25, 2025 am 12:12 AM

MySQL中有四种主要的索引类型:B-Tree索引、哈希索引、全文索引和空间索引。1.B-Tree索引适用于范围查询、排序和分组,适合在employees表的name列上创建。2.哈希索引适用于等值查询,适合在MEMORY存储引擎的hash_table表的id列上创建。3.全文索引用于文本搜索,适合在articles表的content列上创建。4.空间索引用于地理空间查询,适合在locations表的geom列上创建。

您如何在MySQL中创建索引?您如何在MySQL中创建索引?Apr 25, 2025 am 12:06 AM

toCreateAnIndexinMysql,usethecReateIndexStatement.1)forasingLecolumn,使用“ createIndexIdx_lastNameEnemployees(lastName); 2)foracompositeIndex,使用“ createIndexIndexIndexIndexIndexDx_nameOmplayees(lastName,firstName,firstName);” 3)forauniqe instex,creationexexexexex,

MySQL与Sqlite有何不同?MySQL与Sqlite有何不同?Apr 24, 2025 am 12:12 AM

MySQL和SQLite的主要区别在于设计理念和使用场景:1.MySQL适用于大型应用和企业级解决方案,支持高性能和高并发;2.SQLite适合移动应用和桌面软件,轻量级且易于嵌入。

MySQL中的索引是什么?它们如何提高性能?MySQL中的索引是什么?它们如何提高性能?Apr 24, 2025 am 12:09 AM

MySQL中的索引是数据库表中一列或多列的有序结构,用于加速数据检索。1)索引通过减少扫描数据量提升查询速度。2)B-Tree索引利用平衡树结构,适合范围查询和排序。3)创建索引使用CREATEINDEX语句,如CREATEINDEXidx_customer_idONorders(customer_id)。4)复合索引可优化多列查询,如CREATEINDEXidx_customer_orderONorders(customer_id,order_date)。5)使用EXPLAIN分析查询计划,避

说明如何使用MySQL中的交易来确保数据一致性。说明如何使用MySQL中的交易来确保数据一致性。Apr 24, 2025 am 12:09 AM

在MySQL中使用事务可以确保数据一致性。1)通过STARTTRANSACTION开始事务,执行SQL操作后用COMMIT提交或ROLLBACK回滚。2)使用SAVEPOINT可以设置保存点,允许部分回滚。3)性能优化建议包括缩短事务时间、避免大规模查询和合理使用隔离级别。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

功能强大的PHP集成开发环境