Apache Arrow 的列式内存格式

news2024/11/14 20:31:00

在这里插入图片描述

Apache Arrow 的列式存储格式是一种内存数据组织标准,它通过物理布局、Array(数组)、Schema(模式)和 RecordBatch(记录批次)等,优化了大数据的存储与处理。这种格式以列而非行来存储数据,从而提高了数据访问效率,支持跨平台和多种编程语言,且无需序列化开销,适应现代硬件架构,特别适合于高效的数据分析操作。

01 概述


下图描述了 Apache Arrow 中列式存储格式的主要组成部分,RecordBatch 是 Apache Arrow 中一组具有相同结构的数组 Array 或分块数组 ChunkedArray 构成的集合,它表示一个逻辑上相关联的数据集,例如数据库表的多行记录。Schema 定义了这些数组的组织结构,并且提供了一种方式来描述和管理这些数组的基本属性和附加信息;每个数组或分块数组在 Schema 中都有一个对应的字段 Field,这个字段记录了数组的名称和数据类型 DataType,这些名称和数据类型可以是用户指定的,也可以是从文件中读取得到的;多个这样的字段被组织在一个 Schema 结构中。

(图片来源:https://img-blog.csdnimg.cn/img_convert/01bee720e9eacb5188ccd107e54e4986.png)

Apache Arrow 中自下而上主要的结构说明如下:

  • Physical Layout(物理布局)Physical Layout (或 DataTypeLayout) 定义了数据类型的内存布局,即如何在内存中表示和组织数据。它描述了数据类型的结构、大小和对齐方式,以及如何存储和访问数据的元数据信息。

  • DataType(数据类型)DataType 是 Apache Arrow 中定义数据的类型和属性的对象,是一种逻辑类型。它描述了数据的基本类型(如整数、浮点数、字符串等),并可以包含其他的元数据信息(如字段名、单位、精度等)。每个 DataType 都与特定的 Physical Layout 关联,以确定数据在内存中的布局和表示方式。

  • Array(数组)Array(或 Vector) 是 Apache Arrow 中的数据容器,用于存储一系列具有相同数据类型的元素。它是在特定 Physical Layout 的基础上创建的,按照特定的内存布局存储数据。Array 提供了对数据的高效访问和操作方法,并支持常见的数组操作,例如索引、切片、过滤等。

  • RecordBatch(记录批)RecordBatch 是 Apache Arrow 中的数据集合,由一组具有相同结构的 Array 组成。它表示一个逻辑上相关联的数据集,例如数据库表的多行记录。RecordBatch 中的每个 Array 代表一个列,而 RecordBatch 中的行数由 Array 的长度确定。RecordBatch 提供了一种高效的方式来处理和传输数据集,支持批处理操作和列式访问模式。

02 物理布局 Physical Layout


Apache Arrow 中的物理布局是其数据组织格式的基础,它决定了数据在内存中的存储方式和组织结构,以实现高效的数据访问、处理和传输。通过优化物理布局,可以提高数据处理的速度和效率,同时支持跨系统和编程语言的数据交换和共享。

物理布局结构体DataTypeLayout的 C++ 实现被定义在cpp\src\arrow\type.h 头文件中,其中定义了 4 种 BufferSpec :FixedWidth(单值定长类型),VariableWidth(变长类型),Bitmap(位图记录空值),AlwaysNull(始终为空)

结构体DataTypeLayout还包含一个 BufferSpec 对象数组的 buffers成员,用于存储每个预期缓冲区的布局规范;has_dictionary成员表示该类型是否期望有一个关联的字典数组;variadic_spec成员是一个可选的BufferSpec 对象,用于指定超出 buffers 大小下限的缓冲区的规范

struct ARROW_EXPORT DataTypeLayout {
  enum BufferKind { FIXED_WIDTH, VARIABLE_WIDTH, BITMAP, ALWAYS_NULL };

  /// Layout specification for a single data type buffer
  struct BufferSpec {
    BufferKind kind;
    int64_t byte_width;  // For FIXED_WIDTH

    bool operator==(const BufferSpec& other) const {
      return kind == other.kind &&
             (kind != FIXED_WIDTH || byte_width == other.byte_width);
    }
    bool operator!=(const BufferSpec& other) const { return !(*this == other); }
  };

  static BufferSpec FixedWidth(int64_t w) { return BufferSpec{FIXED_WIDTH, w}; }
  static BufferSpec VariableWidth() { return BufferSpec{VARIABLE_WIDTH, -1}; }
  static BufferSpec Bitmap() { return BufferSpec{BITMAP, -1}; }
  static BufferSpec AlwaysNull() { return BufferSpec{ALWAYS_NULL, -1}; }

  /// A vector of buffer layout specifications, one for each expected buffer
  std::vector<BufferSpec> buffers;
  /// Whether this type expects an associated dictionary array.
  bool has_dictionary = false;
  /// If this is provided, the number of buffers expected is only lower-bounded by
  /// buffers.size(). Buffers beyond this lower bound are expected to conform to
  /// variadic_spec.
  std::optional<BufferSpec> variadic_spec;

  explicit DataTypeLayout(std::vector<BufferSpec> buffers,
                          std::optional<BufferSpec> variadic_spec = {})
      : buffers(std::move(buffers)), variadic_spec(variadic_spec) {}
};

基于DataTypeLayout结构体中的 4 种 BufferSpec 进行组合使用,Apache Arrow 提供了多种物理布局类型如下表所示:

Layout TypeBuffer 0Buffer 1Buffer 2Variadic Buffers
Primitivevaliditydata
Variable Binaryvalidityoffsetsdata
Variable Binary Viewvalidityviewsdata
Listvalidityoffsets
List Viewvalidityoffsetssizes
Fixed-size Listvalidity
Structvalidity
Sparse Uniontype ids
Dense Uniontype idsoffsets
Null
Dictionary-encodedvaliditydata (indices)
Run-end encoded
  • 固定大小的原始类型(Primitive (fixed-size)):具有相同字节或位宽的值序列
  • 可变大小的二进制类型(Variable-size Binary):具有可变字节长度的值序列,支持使用 32 位和 64 位长度编码的两种变体
  • 可变大小二进制的视图(View of Variable-size Binary):具有可变字节长度的值序列,与可变大小二进制不同,这种布局的值分布在可能多个缓冲区中,而不是密集且顺序地打包在单个缓冲区中
  • 可变大小的列表(Variable-size List):一种嵌套布局,其中每个值是来自子数据类型的可变长度值序列,支持使用 32 位和 64 位长度编码的两种变体
  • 可变大小列表的视图(View of Variable-size List):一种嵌套布局,其中每个值是来自子数据类型的可变长度值序列;这种布局与可变大小列表不同,它有一个额外的缓冲区包含每个列表值的大小。这消除了偏移量缓冲区必须有序的限制
  • 固定大小的列表(Fixed-size List):一种嵌套布局,其中每个值具有相同数量的元素,来自子数据类型 child array
  • 结构体(Struct):由具有相同长度但可能不同类型命名子字段的集合组成的嵌套布局
  • 稀疏和密集联合(Sparse and Dense Union):一种嵌套布局,表示一系列值的序列,每个值的类型都可以从一系列子数组类型中选择
  • 空值(Null):一系列全部为 null 的值序列
  • 字典编码(Dictionary-Encoded):由整数序列组成的布局(任何位宽),这些整数代表索引到可能为任何类型的字典中
  • 运行结束编码(Run-End Encoded, REE):由两个子数组组成的嵌套布局,一个表示值,一个表示相应值运行结束的逻辑索引

03 数据类型 DataType


基于物理布局 physical layout,Arrow 提供了一套对应的逻辑类型 logical type,即 DataType

根据物理布局中的定长类型(Fixed-size)和变长类型(Variable-size)等类型划分,Arrow 提供了如下种类的数据类型:

  • 定长类型(FixedWidthType):Boolean, Int, Floating Point, Decimal, Date, Time, Timestamp, Interval, Duration
  • 嵌套类型(Nested Types):List, Struct, Map, Union

这些类型的 C++ 实现被定义在cpp\src\arrow\type.h 头文件中,类型之间的派生关系如下(参考原文:Apache arrow 极致模块化、可组合的数据平台-CSDN博客)

/*
 * ListType  LargeListType FixedListType
 *    │             │            │
 *    │             ▼            │
 *    └───────► BaseListType◄────┘     StructType          UnionType         RunEndEncodedType
 *                     │                   │                   │                   │
 *                     │                   │                   │                   │
 *                     └───────────────────┴───►NestedType◄────┴───────────────────┘            ExtensionType
 *                                                   │                                               │
 *                                                   │                                               │
 *                                                   └──────────────► DataType ◄─────────────────────┘
 *                                                                      ▲
 *                                                                      │
 *                   ┌────────────────┬──────────────────────┬────►FixedWidthType ◄───┬─────────────────────┬─────────────────┐
 *                   │                │                      │                        │                     │                 │
 *                   │                │                      │                        │                     │                 │
 *                   │                │                      │                        │                     │                 │
 *           DictionaryType   PrimitiveType           ┌─►NumberType◄──┐           TemporaType     FixedSizeBinaryType   BaseBinaryType
 *                                                    │               │                ▲                    ▲            ▲         ▲
 *                                                    │               │                │                    │            │         │
 *                                                IntegerType FloatingPointType   ┌─►DateType◄──┐      DecimalType  StringType  LargeStringType
 *                                                                                │             │         ▲      ▲
 *                                                                                │             │         │      │
 *                                                                             Date32Type  Date64Type 128Type, 256Type
 */

Arrow 提供的数据类型详细如下表:(参考原文:Arrow Columnar Format — Apache Arrow v18.0.0.dev61)

TypeType ParametersPhysical Layout
NullNull
BooleanFixed-size Primitive
Int- bit width
- signedness
Floating Point- precision
Decimal- bit width
- scale
- precision
Date- unit
Time- bit width
- unit
Timestamp- unit
- timezone
Interval- unit
Duration- unit
Fixed-Size Binary- byte widthFixed-size Binary
BinaryVariable-size Binary with 32-bit offsets
Utf8
Large BinaryVariable-size Binary with 64-bit offsets
Large Utf8
Binary ViewVariable-size Binary View
Utf8 View
Fixed-Size List- value type
- list size
Fixed-size List
List- value typeVariable-size List with 32-bit offsets
Large List- value typeVariable-size List with 64-bit offsets
List View- value typeVariable-size List View with 32-bit offsets and sizes
Large List View- value typeVariable-size List View with 64-bit offsets and sizes
Struct- childrenStruct
Map- children
- keys sortedness
Variable-size List of Structs
Union- children
- mode
- type ids
Dense or Sparse Union
Dictionary- index type
- value type
- orderedness
Dictionary Encoded
Run-End Encoded- run end type
- value type
Run-End Encoded

04 数组 Array


Array 数据结构被定义为 ArrayData 包括如下主要属性:

  • type (DataType):指向 DataType 类型的共享指针,表示数组的数据类型
  • length (int64_t):表示数组的长度
  • null_count (int64_t):可变的 atomic<int64_t>类型,表示数组的空值计数
  • offset (int64_t):表示逻辑上进入物理缓冲区 Buffer 的起始点
  • buffers (vector<Buffer>):存储 Buffer 类型共享指针的向量,表示数组的缓冲区
  • child_data (vector<ArrayData>):存储 ArrayData 类型共享指针的向量,表示数组的子数组
  • dictionary (ArrayData):指向 ArrayData 类型的共享指针,表示数组的字典,仅用于字典类型
struct ARROW_EXPORT ArrayData {
  // ...
  std::shared_ptr<DataType> type;
  int64_t length = 0;
  mutable std::atomic<int64_t> null_count{0};
  // The logical start point into the physical buffers (in values, not bytes).
  // Note that, for child data, this must be *added* to the child data's own offset.
  int64_t offset = 0;
  std::vector<std::shared_ptr<Buffer>> buffers;
  std::vector<std::shared_ptr<ArrayData>> child_data;

  // The dictionary for this Array, if any. Only used for dictionary type
  std::shared_ptr<ArrayData> dictionary;
};

不同数据类型的 Array 的物理布局也不一样,下面结合实例介绍几种常用物理布局类型的 Array 数组的数据组织方式(原文参考:《In-Memory Analytics with Apache Arrow》,本节相关图片也来源于此)

4.1 Fixed-size Primitive Layout

Primitive 类型的数组表示一个值数组,每个值具有相同的物理插槽(physical slot)宽度(固定长度数据类型的所占内存空间大小),通常以字节为单位

例如:一个Int32类型的数组 [1, null, 2, 4, 8],则该数组的 length = 5; null_count = 1

该数组的 buffers中包含两个 Buffer:

  • Validity Bitmap Buffer:与数组中值有效性相关联的位图,该 Bitmap 的内存空间是被连续分配,但是不需要和Value Buffer在内存空间中相邻
  • Value Buffer:一个连续的内存缓冲区用于保存数组的值,其总大小至少与插槽宽度乘以数组长度一样大

Int32类型数组例子的物理布局如下图所示:

4.2 Variable-size Binary Layout

Variable-size Binary Layout 是用于存储可变大小二进制数据类型的布局方式,可变大小二进制数据类型通常用于表示字符串、变长字节数组等可变长度的二进制数据

例如:一个字符串类型的数组 ['Water', 'Rising'],则该数组的 length = 2; null_count = 0

该数组的 buffers中包含三个 Buffer:

  • Validity Bitmap Buffer:与数组中值有效性相关联的位图,该 Bitmap 的内存空间是被连续分配,但是不需要和Value Buffer在内存空间中相邻
  • Offsets Buffer:偏移量缓冲区是一个整数数组,用于存储每个元素的起始偏移量;偏移量表示了每个元素在数据缓冲区中的起始位置,通过偏移量,可以快速定位和访问每个元素的数据;Offsets Buffer的偏移量通常从 0开始以Value Buffer的实际长度值为结束,例如本例子中偏移量缓冲区的值为 [0, 5, 11]分别对应了元素值 Water的起始位置 0 和元素值 Rising的起始位置 5,以及Value Buffer的实际长度 11
  • Value Buffer:数据缓冲区是一个字节数组,用于存储实际的二进制数据;数据缓冲区包含了所有元素的二进制数据,通过偏移量缓冲区中的偏移量,可以确定每个元素在数据缓冲区中的位置

字符串类型数组例子的物理布局如下图所示:

4.3 Variable-size List Layout

List 是一种嵌套类型,其中每个值是来自子数据类型的可变长度值序列,在语义上类似于上面介绍的可变大小二进制数据类型 Variable-size Binary

例如:一个Int8类型的 List 数组 [[12, -7, 25], null, [0, -127, 127, 50], []],则该数组的 length = 4; null_count = 1

该数组的 buffers中包含两个 Buffer:

  • Validity Bitmap Buffer:与数组中值有效性相关联的位图,该 Bitmap 的内存空间是被连续分配
  • Offsets Buffer:偏移量缓冲区和 Variable-size Binary 布局类型一样是一个整数数组,用于存储每个元素的起始偏移量;与前者不同的是其偏移量表示的是子数组(Child Array)中的数据缓冲区,而不是引用一个额外的数据缓冲区;例如本例子中偏移量缓冲区的值为 [0, 3, 3, 7, 7]分别对应了第一个数组[12, -7, 25]的起始位置 0 ,第二个 NULL 值元素和第三个数组[0, -127, 127, 50]起始位置 3,第四个空数组[]的起始位置 7,以及子数组Value Buffer的实际长度 7

该数组的数据放在嵌套结构child_data中,其 Child Array 是一个Primitive Int8类型的数组,该数组的 length = 7; null_count = 0,包含不使用的 Validity Bitmap Buffer和存储实际数据值的Value Buffer两个缓冲区,其中上层的 Offsets Buffer中的偏移量与 Child Array 中的 Value Buffer 对应

4.4 Fixed-Size List Layout

FixedSizeList 是一种嵌套布局,其每个数组槽都包含一个固定大小的值序列,这些值都具有相同的数据类型

例如:一个Int8类型固定长度为 2 的 FixedSizeList 数组 [[10, null], null, [0, 5]],则该数组的 length = 3; null_count = 1

该数组的 buffers中仅包含一个Validity Bitmap Buffer表示与数组中值有效性相关联的位图,该 Bitmap 的内存空间是被连续分配

该数组的数据放在嵌套结构child_data中,其 Child Array 是一个Primitive Int8类型的数组,该数组的 length = 6; null_count = 3,包含表示子数组中数据有效性的 Validity Bitmap Buffer和存储实际数据值的Value Buffer两个缓冲区

4.5 Struct Layout

Struct 是一种嵌套类型,它通常由多个字段(Field)组成,所以 Struct Layout 通常是具有相同长度但可能不同类型命名子字段的集合组成的嵌套布局

例如:包含两个属性的Struct<name: VarBinary, age: Int32>结构体类型数组 [{'joe', 1}, {null, 2}, null, {'mark', 4}],则该数组的 length = 4; null_count = 1

该数组的 buffers中仅包含一个Validity Bitmap Buffer表示与数组中值有效性相关联的位图,该 Bitmap 的内存空间是被连续分配

这种类型的物理布局中,一个 Struct 数组的每个字段都有一个对应的子数组 Child Array,在本例中 Struct 的 name 和 age 两个字段的数据分别被存储在嵌套结构child_data的两个 Child Array:Field-0 和 Field-1 中

  • Field-0 是一个 Variable-size Binary Layout 物理布局的 String类型数组,其值为 ['joe', null, null, 'mark'],该子数组的 length = 4; null_count = 2,buffers 中包含Validity Bitmap Buffer, Offsets BufferValue Buffer三个缓冲区
  • Field-1 是一个 Fixed-size Primitive Layout 物理布局的 Int32类型数组,其值为 [1, 2, null, 4],该子数组的 length = 4; null_count = 1,buffers 中包含Validity Bitmap BufferValue Buffer两个缓冲区

4.6 Union Layout

Union 是一种可以让同一数组中存储不同数据类型数据值的嵌套类型,它由有序的类型序列定义,Union 类型的数组中每一个物理插槽都是从这些类型中选择一个值;与其他数据类型不同,Union Layout 没有自己的有效性位图,其每个槽的空值由其按数据类型划分的子数组各自确定

针对不同的应用场景,Arrow 中提供了 Dense 和 Sparse 两种不同的 Union Layout,其中 Dense 使用了一个额外的类型标签缓冲区 Types Buffer 和一个偏移量数组 Offsets Buffer 来存储每个值的类型信息和偏移量信息;而 Sparse 则仅使用了一个额外的类型标签缓冲区 Types Buffer 来存储每个值的类型信息;数组实际的数据值被按数据类型划分存储在不同的子数组 Child Array 中

例如:包含两个数据类型的Union<f: Float, i: Int32>联合类型数组 [{f=1.2}, null, {f=3.4}, {i=5}],则该数组的 length = 4; null_count = 0

如果该数组使用 Dense Union Layout 物理布局方式,则该数组的 buffers 字段包含一个额外的类型标签缓冲区 Types Buffer 和一个偏移量数组 Offsets Buffer 来存储每个值的类型信息和偏移量信息的两个缓冲区;该数组实际的数据值被按数据类型划分采用 Fixed-size Primitive Layout 布局方式的 Float 和 Int32 两个子数组 Child Array 各自存储,其物理布局如下图所示:

如果该数组使用 Sparse Union Layout 物理布局方式,则该数组的 buffers 字段仅包含一个存储每个值类型信息的类型标签缓冲区 Types Buffer;该数组实际的数据值同样被按数据类型划分采用 Fixed-size Primitive Layout 布局方式的 Float 和 Int32 两个子数组 Child Array 各自存储,其物理布局如下图所示:

4.7 Dictionary-encoded Layout

Dictionary-encoded Layout 是用于存储字典编码数据类型的布局方式,任何数组都可以进行字典编码,当字段进行字典编码时,值由表示字典中值索引的非负整数数组表示;字典编码数组的内存布局与Primitive Int布局的内存布局相同,字典作为具有自身相应布局的单独列式数组处理。

例如:一个 String 类型字典编码数组 ['foo', 'bar', 'foo', 'bar', null, 'baz'],则该数组的 length = 6; null_count = 1

该数组的 buffers 与Primitive Int布局一致包含两个 Buffer:

  • Validity Bitmap Buffer:与数组中值有效性相关联的位图,该 Bitmap 的内存空间是被连续分配
  • Value Buffer:一个连续的内存缓冲区用于保存字典中值的索引,其总大小至少与插槽宽度乘以数组长度一样大

当数组使用字典编码时,使用dictionary属性中的子数组 Dictionary Array 来保存压缩的数据值。例如本例中 Dictionary Array 是一个 Variable-size Binary Layout 物理布局的 String 类型数组,该数组的 length = 3; null_count = 0,buffers 包含不使用的 Validity Bitmap Buffer,保存数据值偏移量的Offsets Buffer和存储实际数据值的Value Buffer三个缓冲区

05 数据集合 RecordBatch


在 Apache Arrow 的列式格式中,RecordBatch 是序列化数据的基本单位,如下图所示,它由多个字段(Field)组成的有序集合构成,每个字段对应一个数组,而每个数组的长度彼此相同,但数据类型可能不同

每个字段 Field 代表了数据集中的一个列,它包含了该列的数据以及元数据信息,其中数据即为对应格式的 Array,数组 Array 中存储对应数据类型的单值 Scalar;每个字段 Field 都包含字段名称和字段的数据类型(DataType),这些字段的名称和类型共同构成了 RecordBatch 的模式 Schema

Schema 定义了 RecordBatch 中每个字段的名称、数据类型和其他属性,是数据集结构的元数据描述(RecordBatch 和 Schema 之间的关系可以类比为数据库中的表和表结构的关系;RecordBatch 就像是表中的部分数据,而 Schema 则是表的结构定义,包含了表中每个列的信息)

在这里插入图片描述

(图片来源:https://blog.djnavarro.net/posts/2022-11-30_unpacking-arrow-datasets/img/record_batch.png)


Arrow 使用 RecordBatch 将 record/row-oriented 的数据转换为 column-oriented 的列格式,在流数据 Data Stream 中 RecordBatch 消息按照 Schema 后面跟一个或多个 RecordBatch 的方式传输数据如下图所示

其中 RecordBatch 消息包含与由 Schema 确定的物理内存布局相对应的实际数据缓冲区 Buffer,每个 RecordBatch 消息的元数据提供了每个缓冲区的位置和大小,允许直接使用指针重建 Array 数据结构,因此无需进行内存复制

RecordBatch 的序列化形式如上图所示,包括 data headerbody两个部分:

  • data header:RecordBatch 消息的元数据,包括每个扁平化(Flattened)字段 Field 的长度和空计数,Body 中每个组成 Buffer 的内存偏移量和长度等信息
/// A data header describing the shared memory layout of a recordbatch. 
table RecordBatch {
  length: long;                 // number of records
  nodes: [FieldNode];           // Nodes correspond to the pre-ordered flattened logical schema
  buffers: [Buffer];            // Buffers correspond to the pre-ordered flattened buffer tree
  compression: BodyCompression; // Optional compression of the message body
  variadicBufferCounts: [long]; // some types use a variable number of buffers
}
  • body:一个扁平的内存缓冲区序列,以端到端的方式写入,并进行适当的填充以确保至少 8 字节对齐

根据 RecordBatch 消息格式,我们可以得出上述例子的序列化形式,首先其 Schema strs: string ints: Int32 dbls: Float64对应的扁平化形式为

FieldNode 0: String name='strs'
FieldNode 1: Int32 name='ints'
FieldNode 2: Float64 name='dbls'

其对应的 buffers 的序列化形式如下,Flatbuffers 值描述了内存片段的位置和大小

buffer 0: field 0 validity
buffer 1: field 0 offsets
buffer 2: field 0 data
buffer 3: field 1 validity
buffer 4: field 1 data
buffer 5: field 2 validity
buffer 6: field 2 data

对于某些类型(如 Utf8View)使用可变数量的缓冲区variadicBufferCounts表示,那些预先排序的扁平化逻辑 Schema 中的每个此类字段,variadicBufferCounts 中将有一个条目,指示当前 RecordBatch 中属于该字段的可变参数缓冲区的数量

例如,如下 Schema,有两个具有可变参数缓冲区的字段 BinaryViewUtf8View

col1: Struct<a: Int32, b: BinaryView, c: Float64>
col2: Utf8View

则 variadicBufferCounts 在每个 RecordBatch 中将有两个条目,对于具有 variadicBufferCounts = [3, 2] 的此模式的 RecordBatch,其扁平化缓冲区为

buffer 0:  col1    validity
buffer 1:  col1.a  validity
buffer 2:  col1.a  values
buffer 3:  col1.b  validity
buffer 4:  col1.b  views
buffer 5:  col1.b  data
buffer 6:  col1.b  data
buffer 7:  col1.b  data
buffer 8:  col1.c  validity
buffer 9:  col1.c  values
buffer 10: col2    validity
buffer 11: col2    views
buffer 12: col2    data
buffer 13: col2    data

如果文章对你有帮助,欢迎 点赞收藏 👍 ⭐️ 💬,如果还能够 点击关注,那真的是对我最大的鼓励 🔥 🔥 🔥

参考资料

Arrow Columnar Format — Apache Arrow v18.0.0.dev61

In-Memory Analytics with Apache Arrow (豆瓣) (douban.com)

Apache arrow 极致模块化、可组合的数据平台-CSDN博客

箭头列式格式 — Apache Arrow v16.1.0 - Arrow 中文

Arrays and tables in Arrow – Notes from a data witch (djnavarro.net)

Unpacking Arrow Datasets – Notes from a data witch (djnavarro.net)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2084595.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

更改网络ip地址时出现错误怎么办

在日常的网络使用中&#xff0c;‌有时我们需要更改IP地址以满足特定的网络需求&#xff0c;‌然而&#xff0c;‌在更改IP地址的过程中&#xff0c;‌可能会遇到各种错误&#xff0c;‌导致无法成功更改或网络连接出现问题。‌‌而更改网络IP地址时出现错误是由于多种原因导致…

二、基于Vue3的开发-环境搭建【Visual Studio Code】扩展组件

Visual Studio Code中的扩展组件 1、安装的扩展工具2、说明2.1 、代码规范性检查EsLint2.2 、代码语法高亮提示工具Vue - Official2.3 、阿里的AI代码开发提示工具 TONGYI Lingma 1、安装的扩展工具 2、说明 2.1 、代码规范性检查EsLint Visual Studio Code 中【设置】-setti…

基于元神操作系统编程写硬盘扇区

1. 背景 本文介绍了“调用元神操作系统API向硬盘扇区写数据”的程序实现及测试结果。 2. 方法 &#xff08;1&#xff09;调用元神操作系统API读硬盘扇区 本部分内容已在前面的文章中进行介绍&#xff0c;详细内容请参考“编写程序调用元神操作系统的API”。 &#xff08;…

二叉树 - 二叉树的所有路径

257. 二叉树的所有路径 方法一&#xff1a;递归法&#xff1a; /*** Definition for a binary tree node.* function TreeNode(val, left, right) {* this.val (valundefined ? 0 : val)* this.left (leftundefined ? null : left)* this.right (rightundefi…

水下目标检测(低光照目标检测)方法-发表在Patter Recognition,代码已开源

这里写自定义目录标题 前言动机贡献Overview一些实验结果数据集主要实验结果实验结果展示 总结 前言 Hi,各位读者&#xff0c;好久不见&#xff01;现在我已经从北大博士毕业&#xff0c;成为一名小青椒啦&#xff01;工作还是需要宣传的。今天想分享我在水下目标检测的工作&a…

低代码技术:快速构建应用的未来

在当今快速发展的数字化时代&#xff0c;企业和个人对软件应用的需求不断增长。然而&#xff0c;传统的软件开发过程通常复杂且耗时。这使得低代码技术&#xff08;Low-Code Technology&#xff09;成为了越来越多人关注的焦点。本文将探讨低代码技术的基本概念、优势以及如何在…

贾湖刻符——汉字起源的重要线索

关注我们 - 数字罗塞塔计划 - 汉字是世界上唯一沿用至今的古老文字系统&#xff0c;其演变历程承载着中华文明的发展和赓续。那么汉字究竟源自何时&#xff1f;是古代神话传说的“昔者仓颉作书&#xff0c;而天雨粟&#xff0c;鬼夜哭”&#xff1b;还是由华夏先民创制的刻划符…

请你学习:前端布局3 - flex

Flexbox布局也叫Flex布局&#xff0c;弹性盒子布局。它的目标是提供一个更有效地布局、对齐方式&#xff0c;并且能够使父元素在子元素的大小未知或动态变化情况下仍然能够分配好子元素之间的间隙。主要思想是使父元素能够调整子元素的宽度、高度、排列方式&#xff0c;从而更好…

AI变现之Midjourney头像定制

前言 Midjourney | 头像定制 1.项目介绍 个性化头像在如今的社交媒体时代变得越来越重要。传统头像照片有时显得普通&#xff0c;而AI绘画头像则能为自己的社交账号增加独特性和吸引力。 通过AI绘画工具制作头像&#xff0c;可以获得一个充满创意和个性的头像&#xff0c;让…

湖南的智榜样网络安全公司开的培训学校参加学习成为网络安全工程师

学习网络安全可以通过以下步骤进行&#xff1a; 获取基础知识&#xff1a;开始学习网络安全之前&#xff0c;建议先获取一些计算机基础知识&#xff0c;包括计算机网络、操作系统、编程语言等方面的知识。这些基础知识将为你理解和学习网络安全提供必要的背景。 学习网络安全基…

数据中台即将消亡,数智基建取而代之?

数据中台即将消亡&#xff0c;数智基建取而代之&#xff1f; 前言数智基建 前言 在当今数字化浪潮汹涌澎湃的时代&#xff0c;企业的发展如同在浩瀚海洋中航行的巨轮&#xff0c;而数据则是推动这艘巨轮前行的强大动力。然而&#xff0c;如何有效地管理和利用数据&#xff0c;…

2024年第十四届APMCM亚太地区大学生数学建模竞赛思路

2024年第十四届亚太地区大学生数学建模竞赛(以下简称“竞赛”)是由中国国际科技促进会物联网工作委员会和北京图象图形学学会联合主办的亚太地区大学生学科类竞赛&#xff0c;竞赛由亚太地区大学生数学建模竞赛组委会负责组织&#xff0c;欢迎各高等院校按照竞赛章程及有关规定…

MySQL:SQL调优的简单实践

记一次简单的SQL优化实践。 一、初始化数据 1.1 初始化数据-课程表 #课程表 create table Course(c_id int primary key,name varchar(10) );#存储过程&#xff1a;增加课程表100条数据DROP PROCEDURE IF EXISTS insert_Course;DELIMITER $CREATE PROCEDURE insert_Course()…

[线程]***多线程带来的风险-线程安全问题

文章目录 一. 什么是线程安全二. 线程不安全一个经典的例子三. 对上述例子的理解四. 出现线程不安全的原因1. 线程在操作系统中是随机调度, 抢占式执行的2. 当前代码中, 多个线程同时修改同一变量3. 线程针对变量的修改操作, 不是"原子"的4. 内存可见性问题, 引起线程…

使用gradle 移除敏感权限

前言 最近要上架Google Play 但是因为有个敏感权限很容易被拒。 想着把权限依赖的库去掉就行了&#xff0c;但是遇到一个恶心的问题。就是这个权限在Android Studio的Merged Manifest 视图中没有&#xff0c;但是在生成的apk中却包含。这样的就不能通过Android Studio来定位权…

一文搞懂 js 原型和原型链

文章目录 一、前言二、原型2.1 概念2.2 获取原型的方法2.2.1 __proto__获取方式2.2.2 通过构造函数prototype 属性获取2.2.2 ES6 class 通过Object.getPrototypeOf()获取类原型 2.3 通过原型实现继承2.4 原型的作用 三、 原型链四、ES6实现继承五、综述 一、前言 原型和原型链…

计算机网络面试真题总结(七)

文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 什么是对称加密、非对称加密&#xff1f; 对称加密是一种常用的加…

C语言 之 自定义类型:结构体、结构体内存对齐、修改默认对齐参数 详细说明 可以来看看哟

结构体类型的声明 结构体的声明 struct tag {member-list; //结构体中的成员&#xff0c;可以有多个 }variable-list; //这里是直接创建结构体的变量&#xff0c;但是不一定要在这里声明变量 //不能把后面这个 ; 省略了例如结构体用于描述一个学生&#xff1a; struct Stu…

MySQL内部临时表(Using temporary)案例详解及优化解决方法

目录 前言 一.场景案例 二、什么是内部临时表&#xff1f; 三、哪些场景会使用内部临时表&#xff1f; 四、内部临时表如何存储&#xff1f; 1&#xff09;使用内存 2&#xff09;先使用内存&#xff0c;再转化成磁盘文件 3&#xff09;直接使用磁盘文件 五、如何优化…

Stable Diffusion绘画 | ControlNet应用-IP-Adapter:一致性角色就这么简单

IP-Adapter 更新了全新的模型—FaceID plus V2 版本&#xff0c;同时还支持 SDXL 模型。 FaceID plus V2 版本的优点&#xff1a; 解决任务一致性 一张图生成相似角色 其中&#xff0c;两个 Lora文件 放置在&#xff1a;SD安装目录\models\Lora 两个 bin文件 放置在&#x…