前段时间遇到一个需求是在一批数据里边,按照分组分别求最小时间字段对应的记录,因为刚看了row_number的函数介绍,就用了此函数,先用一个子查询,对数据分组,根据时间排序,得到每行的行号,然后求出行号是1的所有数据。具体为select * from (select a,b,c,row_number() over(distribute by a sort by time) rn
from table) x where rn=1; 此任务一直运行的正常没出什么问题,结果某个特殊的活动日,数据量激增,在reduce阶段内存溢出。因为排序会将符合某个a值的记录全部分到同一个reduce节点,就注定了这是无法通过增加reduce个数来改变的,而整个分布式集群的内存是有限的,每个节点能够使用的内存也是被限制的,不可能无限增加内存,所以就考虑改写sql,避开这种情况。其实当时在用row_number之前就曾考虑的做法是先做一个新表求出每组的最小时间,然后拿原表与新表join,就可以得到最小值对应的记录。此做法有两个问题:1)不够高大上 2)如果有多条记录都符合最小值条件,就没法拿到唯一记录。所以当时选了row_number.
而当数据量激增,面临问题后,又重新考虑原来的方法,唯一需要解决的问题就是第2点,而这一条恰好可以通过row_number解决,所以,我选择了结合两种方法一起解决此问题,首先求最小值,再与原表join,得到的记录有重复值,就用row_number再重新排序一次,因为此时的数据量已经很小,而且只有特殊的组有重复记录,重复记录也不会特别多,也就不会发生reduce节点内存溢出的问题。