Hive row_number,rank两个函数的区别
窗口函数也称为OLAP(Online Analytical Processing)函数
,是对一组值进行操作,不需要使用Group by子句
对数据进行分组
,还能在同一行返回原来行的列和使用聚合函数
得到的聚合列
那为什么叫窗口函数呢?因为窗口函数将表以窗口
为单位
进行分割
,并在其中进行各种分析操作,为了让大家快速形成直观印象,才起了这样一个容易理解的名称
排序对应的四个窗口函数为:rank、dense_rank、row_number、ntitle
rank:计算排序时,如果存在相同位次的记录,则会跳过之后的位次。
e.g. 有三条记录排在第1位时:1位、1位、1位、4位......
dense_rank:计算排序时,即使存在相同位次的记录,也不会跳过之后的位次。
e.g. 有三条记录排在第1位时:1位、1位、1位、2位......
row_number:赋予唯一的连续位次。
e.g. 有三条记录排在第1位时:1位、2位、3位、4位...
ntitle:用于将分组数据按照顺序切分成n片,返回当前切片值
e.g. 对于一组数字(1,2,3,4,5,6),ntile(2)切片后为(1,1,1,2,2,2)
Hive窗口函数怎么设置窗口大小
窗口大小的设置(也叫window子句)
默认窗口大小是从起始行到当前行
partition by …order by…rows between unbounded preceding and current row
窗口大小为从起始行得到当前行。
partition by …order by… rows between 3 preceding and current row
窗口大小为从当前行到之前三行
partition by …order by… rows between 3 preceding and 1 following
窗口大小为当前行的前三行到之后的一行
partition by …order by… rows between 3 preceding and unbounded following
窗口大小为当前行的前三行到之后的所有行
Hive order by,sort by,distribute by,cluster by 区别
sort by代替order by
HiveQL中的order by与其他SQL方言中的功能一样,就是将结果按某字段全局排序,这会导致所有map端数据都进入一个reducer中,在数据量大时可能会长时间计算不完。
如果使用sort by
,那么还是会视情况启动多个reducer
进行排序
,并且保证每个reducer内局部有序
。为了控制map端数据分配到reducer的key,往往还要配合distribute by一同使用。如果不加distribute by
的话,map端数据就会随机分配到reducer
select uid,upload_time,event_type,record_data
from calendar_record_log
where pt_date >= 20190201 and pt_date <= 20190224
distribute by uid
sort by upload_time desc,event_type desc;
-
order by
Hive中的order by跟传统的sql语言中的order by作用是一样的,会对查询的结果做一次全局排序,所以说,只有hive的sql中制定了order by所有的数据都会到同一个reducer进行处理(不管有多少map,也不管文件有多少的block只会启动一个reducer)。但是对于大量数据这将会消耗很长的时间去执行。
这里跟传统的sql还有一点区别:如果指定了hive.mapred.mode=strict(默认值是nonstrict),这时就必须指定limit来限制输出条数,原因是:所有的数据都会在同一个reducer端进行,数据量大的情况下可能不能出结果,那么在这样的严格模式下,必须指定输出的条数。 -
sort by
Hive中指定了sort by,那么在每个reducer端都会做排序,也就是说保证了局部有序(每个reducer出来的数据是有序的,但是不能保证所有的数据是有序的,除非只有一个reducer),好处是:执行了局部排序之后可以为接下去的全局排序提高不少的效率(其实就是做一次归并排序就可以做到全局排序了)。 -
distribute by和sort by一起使用
ditribute by是控制map的输出在reducer是如何划分的,举个例子,我们有一张表,mid是指这个store所属的商户,money是这个商户的盈利,name是这个store的名字
Hive map,reduce数怎么设置
可以直接通过参数mapred.map.tasks(默认值2)来设定mapper数的期望值,但它不一定会生效,下面会提到。
参数mapred.min.split.size(默认值1B)和mapred.max.split.size(默认值64MB)分别用来指定split的最小和最大大小
-
默认map个数
default_num=total_size/block_size; -
期望大小
goal_num=mapred.map.tasks; -
设置处理的文件大小
split_size=max(mapred.min.split.size,block_size);
split_num=total_size/split_size; -
计算的map个数
compute_map_num=min(split_num,max(default_num,goal_num)) -
如果想
减少mapper数
,就适当调高mapred.min.split.size,split数
就减少了。如果想增大mapper数
,除了降低mapred.min.split.size
之外,也可以调高mapred.map.tasks
。
一般来讲,如果输入文件是少量大文件,就减少mapper数;如果输入文件是大量非小文件,就增大mapper数;至于大量小文件的情况,得参考下面“合并小文件”一节的方法处理。
调整reducer数
reducer数量的确定方法比mapper简单得多。使用参数mapred.reduce.tasks
可以直接设定reducer数量
,不像mapper一样是期望值。但如果不设这个参数的话,Hive就会自行推测,逻辑如下:
参数hive.exec.reducers.bytes.per.reducer
用来设定每个reducer能够处理的最大数据量,默认值1G(1.2版本之前)或256M
(1.2版本之后)。
参数hive.exec.reducers.max
用来设定每个job的最大reducer数量,默认值999(1.2版本之前)或1009(1.2版本之后)。
得出reducer数:
reducer_num = MIN(total_input_size / reducers.bytes.per.reducer, reducers.max)。
reducer数量与输出文件的数量相关。如果reducer数太多,会产生大量小文件,对HDFS造成压力。如果reducer数太少,每个reducer要处理很多数据,容易拖慢运行时间或者造成OOM
合并小文件
输入阶段合并
需要更改Hive的输入文件格式,即参数hive.input.format,默认值是org.apache.hadoop.hive.ql.io.HiveInputFormat,我们改成org.apache.hadoop.hive.ql.io.CombineHiveInputFormat。
这样比起上面调整mapper数时,又会多出两个参数,分别是mapred.min.split.size.per.node
和mapred.min.split.size.per.rack
,含义是单节点和单机架上的最小split大小。如果发现有split大小小于这两个值(默认都是100MB),则会进行合并。具体逻辑可以参看Hive源码中的对应类。
输出阶段合并
直接将hive.merge.mapfiles
和hive.merge.mapredfiles
都设为true即可,前者表示将map-only任务的输出合并,后者表示将map-reduce任务的输出合并。
另外,hive.merge.size.per.task可以指定每个task输出后合并文件大小的期望值,hive.merge.size.smallfiles.avgsize可以指定所有输出文件大小的均值阈值,默认值都是1GB。如果平均大小不足的话,就会另外启动一个任务来进行合并。
Hive SQL数据倾斜有哪些原因?怎么优化
parquet数据格式内部结构了解吗
Hive数据选择的什么压缩格式
Hive SQL 如何转化成MR任务的
Hive 分桶了解吗
Hive的udf、udaf和udtf了解过吗?自己有没有写过udf
怎么验证Hive SQL 的正确性
lateral view explode关键字来拆分数组
join操作底层的MapReduce是怎么去执行的
网友评论