一.前言
本文只要探索在Presto中groupby是怎么实现的。在Preso中,groupby的分组主要通过对数据Hash的数值比较进行分组,其中有2种情况,一直是仅有一个groupby字段而且字段是Bigint类型的,此场景下会使用BigintGroupByHash来实现分组,其他的情况则使用MultiChannelGroupByHash实现多列分组。
二. BigintGroupByHash分组的实现
在理解BigintGroupByHash实现分组过程前,需要先了解BigintGroupByHash中几个全部变量的意义:
groupId : 一个累增的数,在groupby字段中,每遇到一个hash后找不到的值时候,此字段+1,起id作用
hashPosition : goupby字段的value的hash值,用来充当在数组中的位置作用
values : 一个key-value对,key值为groupby字段的value值的HashPisition,value为groupby字段的value
groupIds : 一个key-value对,key值为HashPosition,value值为groupId
valuesByGroupId :一个数组,在groupId的下标处放置 value
GroupCount:groupby字段groupby后的数量
了解上边字段的意义后,如下通过Hash实现分组的流程则比较容易于理解:
三. MultiChannelGroupByHash分组的实现
MultiChannelGroupByHash多列分组的流程和BigintGroupByHash差不多,如下为其和单列分组不同的地方:
MultiChannelGroupByHash的hashPosition的数据是经过二级Hash后的数据,第一次Hash是将多列groupby列的数据每列都进行Hash按照一定的公式求和得到,然后再对一级Hash后的结果进行二级Hash计算后得到。
MultiChannelGroupByHash的address计算和BigintGroupByHash不一样,多列分组的address一个pageIndex << 32 | pageOffset计算得到的。
多列分组因为涉及到多列数据,因此不使用values存储groupId与values的关系,而是采用了Page(currentPageBuilder)的方式存储。还原数据的时候会从Page中根据address拿到postion然后读出数据进行还原和聚合。