Presto如何開發自定義聚合函數

(一)先了解一下什麼是自定義聚合函數

  1. 其實就是根據你自己的業務去進行定義你自己想要實現的方法,比如說Mysql中的sum() 方法,就是求某個字段的累加之和,那麼你就可以自己實現自己的 比如說 add() 自定義聚合函數方法

(二)如何開發自定義聚合函數

  1. 首先需要實現Presto提供的Plugin接口,然後把要實現的聚合函數所在的類添加到集合中
package com.tapdb.analytics.presto.udaf;

import com.google.common.collect.ImmutableSet;
import io.prestosql.spi.Plugin;

import java.util.Set;

public class TapdbAnalyticsPlugin implements Plugin {

    @Override
    public Set<Class<?>> getFunctions() {
        return ImmutableSet.<Class<?>>builder()
                .add(DateHistogramAggregation.class)
                .add(ArraySumAggregation.class)
                .add(ArrayConstructScalar.class)
                .add(RetentionAggregation.class)
                .add(DecodeBitSetAggregation.class)
                .build();
    }
}
  1. 然後把你想要處理的字段根據其類型傳入input()方法的參數中進行處理,這裏需要注意如何把你處理好的結果集傳給下一個combine()方法,需要通過SliceState進行作爲橋樑,當然這個也可以自己進行自定義,output()方法是把最後的結果集進行構造然後,通過Presto提供的API進行構建返回結果。
package com.tapdb.analytics.presto.udaf;

import io.airlift.slice.Slice;
import io.airlift.slice.Slices;
import io.prestosql.spi.block.BlockBuilder;
import io.prestosql.spi.function.*;
import io.prestosql.spi.type.StandardTypes;

/**
 * @Description DecodeBitSetAggregation
 * @Date 2020/6/16
 * @Author wangwei
 */
@AggregationFunction("tapdb_bitset_decode")
public class DecodeBitSetAggregation {

    @InputFunction
    public static void input(@AggregationState SliceState state,
                             @SqlType(StandardTypes.BIGINT) long mask,
                             @SqlType(StandardTypes.BIGINT) long value) {
        if (state.getSlice() == null) {
            long capacity = 30 * Long.BYTES;
            Slice slice = Slices.allocate((int) capacity);
            state.setSlice(slice);
        }
        Slice slice = state.getSlice();
        long retainValue = mask <= 0 ? value ^ mask : value & mask;
        int tmpIndex = 0;
        for (int i = 29; i >= 0; i--) {
            int offset = Long.BYTES * tmpIndex;
            slice.setLong(offset, Long.lowestOneBit(retainValue) == 1 ? 1L : 0L);
            retainValue = retainValue >> 1;
            tmpIndex++;
        }
    }


    @CombineFunction
    public static void combine(@AggregationState SliceState state, @AggregationState SliceState otherState) {
        Slice otherSlice = otherState.getSlice();
        Slice slice = state.getSlice();

        if (otherSlice == null) {
            return;
        }
        if (slice == null) {
            state.setSlice(otherSlice);
            return;
        }

        int indexNum = slice.length() / Long.BYTES;
        for (int i = 0; i < indexNum; ++i) {
            int offset = i * Long.BYTES;
            slice.setLong(offset, slice.getLong(offset) + otherSlice.getLong(offset) > 0 ? 1L : 0L);
        }
    }


    @OutputFunction("array(bigint)")
    public static void output(@AggregationState SliceState state, BlockBuilder out) {
        Slice slice = state.getSlice();
        if (slice == null) {
            out.appendNull();
            return;
        }

        int byteArrayNum = slice.length() / Long.BYTES;
        BlockBuilder blockBuilder = out.beginBlockEntry();

        for (int i = 0; i < byteArrayNum; ++i) {
            int offset = i * Long.BYTES;
            long value = slice.getLong(offset);
            blockBuilder.writeLong(value).closeEntry();
        }
        out.closeEntry();
    }

}

  1. 就是把這個項目打包成一個jar包,然後放到Presto集羣所有機器下面的plugin目錄下(這裏需要自己隨便創建一個目錄,然後放到自己創建的目錄下),然後就是重啓集羣,使用show functions 查看一下自己定義的聚合函數是不是註冊成功,如果成功如圖這種。
    在這裏插入圖片描述
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章