列式存储
在调试flink读取parquet文件时,读出来的数据是ColumnarRowData
,由于parquet是列式存储的文件格式,所以需要用一种列式存储的表示方式,ColumnarRowData
就是用来表示列式存储的一行数据,它包含多个数组的数据结构,每个数组都代表一个列,并且数组中的元素是该列中的值,系统可以有效地加载和处理需要的列,从而提高查询性能,并减少不必要的数据访问和计算。
- 行存储
GenericRowData
与ColumnarRowData
都是RowData
的实现类,前者是标准的行存储,所有列的值保存在一维数组Object[] fields
中,访问某一列只需要指定列的索引即可。
成员变量
- vectorizedColumnBatch:
VectorizedColumnBatch
类型,一组行数据的集合,可以看成一个二维表,同一列的值保存在同一个数组中(ColumnVector
)。因此,要访问某行某列的值,需要确定行索引rowId与列索引*pos - rowId:行索引,唯一表示某一行。不同的行数据
ColumnarRowData
中,rowId不同,vectorizedColumnBatch相同
根据不同列的类型,会使用对应的Vector进行存储
HeapBooleanVector
HeapBytesVector
HeapByteVector
HeapDoubleVector
HeapFloatVector
HeapIntVector
HeapLongVector
HeapShortVector
HeapTimestampVector
逻辑结构
ParquetColumnarRowSplitReader.nextRecord
按行获取数据时,只是移动了rowId的偏移量,因为数据已经提前在nextBatch
批量从parquet文件中加载到了VectorizedColumnBatch
中。
示例
对于一个parquet文件,有如下数据
id(string) | col1(int) | name(string) | create_date(string) | col2(int) |
---|---|---|---|---|
20 | 12345 | 2020 | 2023-07-19 | 54321 |
生成的ColumnarRowData
对象如下
默认以2048批量,所以底层数组初始长度都为2048
- int类型对应
HeapIntVector
,底层用buffer:int[]存储,一个元素是一个列的值 - string类型对应
HeapBytesVector
,底层用buffer:byte[]存储,第n行的列值由start[n-1]及length[n-1]可定位到对应的字节,第一行的name字节为[50,48,50,48],即“2020”