场景一:
假如我有一张表有10亿条数据,我该如何对这10亿条数据进行排序取TOP10
方法一:采用分桶表
将这张表作为分桶表,确定好分桶字段和分桶数量,根据数据量,假如我们分10个桶,那么每个桶内是1亿条数,对多个一亿条数据分别做排序处理取TOP10,最后再union all起来排序取TOP10
首先分桶就是分文件,分桶表为什么要做成不同的桶分文件的形式?就是为了取桶时一下可以取整个文件,实现分而治之的思想,而不是去一整个文件里找出想要的行,那样分桶就失去了意义,分而治之首先就已经失败了
分桶表和分区表的区别是什么?分桶表也类似于分区表,快速的进行行过滤,但它的行过滤可不是为了取某些个日期进行整体处理,而是为了取各个桶放入不同的reduce,分而治之,这一点是本质上不同的
为什么要取每个桶内的TOP10呢?因为有可能TOP10都正好被分到了同一个桶内
既然分桶表本来就是分而治之,为什么不直接取整个桶表的TOP10?因为如果取的话,给你展现出的Limit 10前十行,只是其中一个桶内的TOP10
方法二:采用Distribute By + Sort By
这种方式的思想也是分而治之,其中的Distribute By分区也类似于分桶表中的分桶,然后Sort By分区内排序,也类似于桶内排序,只不过最后没法直接拿出TOP10,参考上述4,我要单独将输出的中间文件,load进入临时表,然后再各个临时表内取前10,最后再union all取TOP10
这种方式于分桶的区别是什么?首先这里多少个分区不像分桶表一样直接可以指定桶数来确定,但也可以通过指定reduce的个数来间接确定分区个数,而且这里的分区,指的也是map阶段的hash分区,指的是reduce个数,也就是每个reduce内,他是分而治之的,而分桶是可以两个reduce对应一个桶的,是可以多个reduce间分而治之的,也可称为分桶而治,这里显然是分区而治
为什么要经过临时表这个中间步骤?因为它与分桶表不同,分桶表的分桶字段是可以直接拿来过滤使用的,显然分而治之起来更加方便,而这种方式显然你是没法给每个reduce分区进行单独编号使用的,而它Distribute By分区的目的也是为了分桶,只是分完桶无法编号而已,故只能在最后通过临时文件去做一个这样的使用,Sort By排序的目的当然也是和对每个桶排序的目的是一样的
总结:
数据量大的表还是尽量做成分桶表,以避免后期有需求,而迫不得已采用Distribute By + Sort By这种比较麻烦的方式去完成分桶的分而治之目的
不仅排序需要分而治之,group by也是一样的道理,麻烦不仅在于分组本身,而且分组后,如何进行avg等聚合逻辑的运算也是相当麻烦的,所以只要牵扯到reduce的过程,甚至包括join操作,显然都是分桶表更为合适
场景二:
假如我有一个sql查询输出了十万以上的结果,但现在hue上只能下载十万行下载不全怎么办?
方法一:通过row_number进行分开下载
将sql里加上一行row_number,over里按照一个字段或多个字段进行排序,确定每次执行结果都唯一,最后将结果where过滤,分多次执行分别过滤出前十万行,和后面的各十万行,最后在excel内拼接
为什么要保证每次执行结果唯一?因为要分多次执行,取不同的行,如果一个字段排序,结果有重复值,则可能第一次执行,该行为第10万行,第二次执行该行又为10万01行,则中间会缺失一行数据
按多少个字段排序合适,怎么确定?首先可以对某个字段group by求下cnt,然后再过滤一下cnt>=2看看是否有结果,若有,说明有重复字段,则增加字段继续进行测试
方法二:采用分桶表
首先我先取某个或多个分桶字段,然后进行任务执行,接着我再采用其他分桶字段再执行,从而达到分而治之的效果,输出多个文件excel内拼接
为什么这里不可以采用每次取不同分区分而治之?因为很多时候我们的需求是一下子取多个分区数据做聚合的,显然是分区表是无法灵活的进行分而治之的
什么情况下都是使用这个方式吗?并不是,例如我本来就是要对分桶字段进行聚合,这时候就可以,因为毕竟还是在一个桶内聚合,都会将同样值的聚合过来,但如果,我要对其他字段进行聚合,这时候就不再合适,因为并没有达到真正意义的聚合只是桶内聚合而已,仍然需要再次对聚合结果进行聚合,但这个时候显然又超过10万行了
可以采用Distribute By+Sort By的方式吗?不可以,而且这里不需要sort by,因为没有排序,另外,Distribute By在这里只是做到了将最终输出结果分桶的目的,但由于其无法编号,显然无法取出每次我们想要的桶,虽然其可以刚好输出多个文件,但由于我们是impala端执行,怎么能知道中间文件在什么地方
总结:
仍然是采用分而治之的思想,但分区表和Distribute By这两种方式是无法完成的,只能通过分桶表或row_number去实现
需要注意的是,这里的分而治之不再是为了一次性执行出结果,而是分多次执行的分而治之