Trino中的Block类型

2022-05-12 00:00:00 数据 的是 数组 类型 嵌套

在使用分布式SQL查询引擎Trino的时候,不可避免地要接触Block 类型,Trino查询获取数据的单元——页(Page)也是以Block类型为基础的, 深入了解Block结构有助于理解Trino内部的数据组织。

Block在Trino中以接口形式出现,Trino定义了几个基本的实现类, 作为基础的Block结构,然后再定义其他更加高层的Block结构,其内部是其他Block的组合,可以这么理解:当你手上有一个Block的数据,其内部的真实数据可能是引用其他的一个或多个Block。本质上Block是个套娃结构,Block对象是个实现了Block接口的嵌套数据对象,Block存储的底层数据都指向了基本的Block实现类。

Block基本实现类

Block基本实现类是指内部包含直接真实数据,不是以嵌套其他Block对象的形式出现的数据类型。其内部的数据以基本类型数组或者Slice对象出现,这里的Slice指的是一块连续内存区域,后面会讲到。

Block的基本实现类有IntArrayBlock, ShortArrayBlock, ByteArrayBlock, LongArrayBlock,Int96ArrayBlock, Int128ArrayBlock, VariableWidthBlock .

IntArrayBlock

IntArrayBlock 内部以整型数组存放该Block的真实底层数据。具体的内存形式如下图:

IntArrayBlock 的底层数据其实就是int[] values boolean[] valueIsNull 这两个数组,这里boolean[] valueIsNull的出现是为了表示某个位置上的值是否为null,毕竟values 是一个基本类型数组,而不是包装类型Integer数组,所以还是需要有个额外的布尔类型数组表示某个位置是否是null。

这里要注意,values 数组和 valueIsNull 数组的长度不一定相同,因为IntArrayBlock只会使用其中的一部分数据,即索引为 [arrayOffset, arrayOffset+positionCount)的区域。所以这个Block在计算其底层数据大小(sizeInByte)的时候,只会统计自己使用的那一部分。

在计算整个类型占用的字节大小(retainedSizeInByte)时,会计算values valueIsNull占用的全部内存,然后再加上这个类自身使用的内存大小(这里要注意,数组是引用类型,在类中只保存了一个引用标记,所以需要额外计算)。

IntArrayBlock类型类似, ShortArrayBlockByteArrayBlock  LongArrayBlock 无非就是把int[]换成了short[] byte[] Long[], 这几个类型此处就不再赘述了。

Int96ArrayBlock和Int128ArrayBlock

由于java中的整型长是64字节,即long类型,那么如何表示更长字节的整型呢?

Trino使用了long+int来表示一个96位的整型。同样,这里的high数组 和 low数组 的长度也没有必要相同,Block对象只会使用其一部分。

由于没有基本类型可以表示96位的整型,所以从Int96ArrayBlock获取数据需要调用getLong()getInt() 两个方法,才能将一个完整的数据取出。并且由于high  low表示的数据高低位不一样,所以在获取数据时要有明确的offset。只能这么调用:

long high = getLong(position, );
int low = getInt(position, 8);

相关文章