一、概述

数据处理首先需要考虑如何表示数据。对于关系表来讲,通常操作的数据都是以 “行” 为单位的。在 SparkSQL 内部实现中, InternalRow 就是用来表示一行行数据的类。此外,InternalRow 中的每一列都 是 Catalyst 内部定义的数据类型。

二、结构

从类的定义来看,InternalRow 作为一个抽象类,包含 $numFields()$ 和 $update$ 方法,以及各列数据对应的 $get$ 与 $set$ 方法,但具体的实现逻辑体现在不同的子类中。

需要注意的是, InternalRow 中都是根据下标来访问和操作列元素的。

三、InternalRow 继承体系

3.1. BaseGenericInternalRow

同样是一个抽象类,实现了 InternalRow 中定义的所有 get 类型方法,这些方法的实现都通过调用类中定义的 genericGet 虚函数进行

3.1.1. GenericInternalRow

使用数组作为底层存储的 InternalRow 实现。

1
def this(size: Int) = this(new Array[Any](size))

3.1.2. SpecificInternalRow

SpecificInternalRow 和 GernericInternalRow 的区别在于构造参数的类型,GernericInternalRow 的构造参数类型是 Array[Any], 一旦创建就不允许通过 $set$ 操作修改;而SpecificInternalRow 的构造参数类型是 Array[MutableValue],允许通过 $set$ 操作修改。

3.1.3. PartitionInternalRow

3.1.4. LongArrayInternalRow

3.1.5. MutableUnsafeRow

UnsafeRow 的辅助类,用于更新 UnsafeRow中 的字段值,主要使用地方在 ColumnAccessor

3.2. UnsafeRow

不采用 Java 对象存储的方式,避免了 JVM 中垃圾回收的代价。 此外, UnsafeRow 对行数据进行了特定的编码,使得存储更加高效。

3.3. Columnar 相关

3.3.1. ColumnarRow

主要用于 ColumnVector 中 getStruct 时返回列原始信息

3.3.2. MutableColumnarRow

是 ColumnarRow 的可变版本,主要是用于 hash map 的聚合计算

3.3.3. ColumnarBatchRow

3.4. JoinedRow

该类主要用于 Join 操作,将两个 InternalRow 放在一起形成新的 InternalRow。 使用时需要注意构造参数的顺序 。

3.5. ProjectingInternalRow