Apache Arrow C++ 入门教程:从零构建 Array、ChunkedArray、RecordBatch 与 Table

发布时间:2026/9/14 9:34:17

Apache Arrow C++ 入门教程:从零构建 Array、ChunkedArray、RecordBatch 与 Table Apache Arrow C 入门教程从零构建 Array、ChunkedArray、RecordBatch 与 Table【免费下载链接】arrowApache Arrow is the universal columnar format and multi-language toolbox for fast data interchange and in-memory analytics项目地址: https://gitcode.com/GitHub_Trending/arrow3/arrow本教程基于 Apache Arrow 官方 C 入门文档basic_arrow.rst及其配套完整示例源码arrow_example.cc编写目标是帮助读者掌握 Arrow 的四大基础数据结构Array、ChunkedArray、RecordBatch与Table。文章将以天 / 月 / 年三类整数数据为例完整演示从标准 C 数组到 Arrow 列式结构的构建流程并深入讲解ArrayBuilder、Schema、Field、Status错误处理宏等底层机制。读完本文你将能够独立编写一个可编译运行的 Arrow C 程序并理解这些结构在内存布局、数据复制与行数上限方面的设计差异。预备知识Pre-requisites在继续之前请确保满足以下三个前提已安装 Arrow C 库安装与构建方式参见 C 构建系统指南其中包含 CMake 配置、依赖安装与编译选项的完整说明。仓库中另附一键构建脚本 build_arrow.sh它会通过cmake /arrow/cpp配置并执行make install。熟悉基本 C 数据结构的使用例如标准数组、std::shared_ptr、std::vector等。了解基本 C 数据类型包括int8_t、int16_t等定宽整数类型。环境搭建Setup动手之前需要先补齐两个脚手架引入必要的头文件以及一个把程序粘合起来的main()入口。头文件IncludesArrow 将全部核心 API 汇总在单一头文件arrow/api.h中引入它即可使用数组、构建器、Schema、表格等全部基础能力#include arrow/api.h #include iostream其中iostream用于向终端输出结果。Arrow 示例源码见 arrow_example.cc。main() 入口与错误处理约定Arrow 的 C 库遵循一条重要的设计约定函数不抛出 C 异常而是返回arrow::Status对象。这与 Arrow 在编译时通常禁用异常或仅作为可选特性的 ABI 策略一致。因此常见的程序骨架如下int main() { arrow::Status st RunMain(); if (!st.ok()) { std::cerr st std::endl; return 1; } return 0; }真正的业务逻辑放在RunMain()中它返回arrow::Statusarrow::Status RunMain() { // 全部业务代码写在这里 return arrow::Status::OK(); }这样的结构配合两个关键宏使用就能实现出错即返回、统一上报的简洁错误处理ARROW_RETURN_NOT_OK(expr)若expr返回的Status表示失败则立即从当前函数返回该StatusARROW_ASSIGN_OR_RAISE(lhs, expr)若expr返回的ResultT失败则直接返回错误Status成功则把结果赋值给左侧变量。这两个宏在示例中被大量使用其定义可追溯到 Arrow 核心头文件arrow/result.h、arrow/status.h等实现中。关于错误处理约定的更多细节可阅读 conventions.rst。构建 Arrow 数组Making an Arrow ArrayArrow 保证Array内部各元素在内存中是连续的columnar 布局因此从标准 C 数组迁移到 Arrow 数组不会带来性能损失却可以获得统一的类型系统与后续的计算、序列化能力。构造Array最直接的方式是使用ArrayBuilder构建器家族Array更底层的技术细节可参考 arrays.rst。构建 int8 数组以天day数据为例数据为 8 位有符号整数。首先创建arrow::Int8Builder并用AppendValues()将标准 C 数组的内容灌入构建器arrow::Int8Builder int8builder; int8_t days_raw[5] {1, 12, 17, 23, 28}; ARROW_RETURN_NOT_OK(int8builder.AppendValues(days_raw, 5));AppendValues(ptr, length)会从days_raw起始连续读取 5 个值写入构建器。如果内存分配失败或参数非法宏会带着错误Status直接返回main()并打印失败原因。随后调用Finish()把构建器中的累积数据压成一个真正的Array输出为std::shared_ptrarrow::Arraystd::shared_ptrarrow::Array days; ARROW_ASSIGN_OR_RAISE(days, int8builder.Finish());Finish()返回arrow::Resultstd::shared_ptrArrayARROW_ASSIGN_OR_RAISE负责解包失败则返回错误Status成功则将结果赋给days。关键点Finish()被调用后构建器状态会自动重置如同新构建器一样因此相同类型的数组可以反复复用同一个构建器。下面复用int8builder构建月month数组int8_t months_raw[5] {1, 3, 5, 7, 1}; ARROW_RETURN_NOT_OK(int8builder.AppendValues(months_raw, 5)); std::shared_ptrarrow::Array months; ARROW_ASSIGN_OR_RAISE(months, int8builder.Finish());以上片段对应示例源码 arrow_example.cc 中的(Doc section: int8builder 1 Append)、(Doc section: int8builder 1 Finish)与(Doc section: int8builder 2)三段。构建 int16 数组ArrayBuilder的类型在声明时即被固定之后不可更改。当切换到年year数据时最小需要 16 位整数因此必须新建arrow::Int16Builder方法完全相同只是数据类型不同arrow::Int16Builder int16builder; int16_t years_raw[5] {1990, 2000, 1995, 2000, 1995}; ARROW_RETURN_NOT_OK(int16builder.AppendValues(years_raw, 5)); std::shared_ptrarrow::Array years; ARROW_ASSIGN_OR_RAISE(years, int16builder.Finish());至此我们得到了三个类型各异的 Arrow 数组daysint8、monthsint8、yearsint16。该段对应源码 arrow_example.cc 的(Doc section: int16builder)。从源码结构可以推断Arrow 为每种数据类型都提供了对应的构建器类如Int8Builder、Int16Builder等它们继承自ArrayBuilder基类AppendValues/Finish等核心接口在cpp/src/arrow/array/builder_primitive.h等头文件中声明。构建 RecordBatchMaking a RecordBatch列式格式只有组成表才能真正发挥威力。第一种表格结构是RecordBatch它内部由多个Array组成因此每个列内部是连续内存但任何追加或拼接操作都需要复制数据因为列长度固定且内存连续。给定现成的Array构建RecordBatch分两步先定义Schema再把它与Array一起交给构造函数。定义 SchemaSchema描述列的元信息每一列由一个Field表示Field包含列名与数据类型Schema把多个Field组织起来并确定列的顺序std::shared_ptrarrow::Field field_day, field_month, field_year; std::shared_ptrarrow::Schema schema; field_day arrow::field(Day, arrow::int8()); field_month arrow::field(Month, arrow::int8()); field_year arrow::field(Year, arrow::int16()); schema arrow::schema({field_day, field_month, field_year});这里使用了便捷工厂函数arrow::field(name, type)与arrow::schema(fields)。数据类型对象同样由工厂函数生成arrow::int8()、arrow::int16()。该段对应源码 arrow_example.cc 的(Doc section: Schema)。组装 RecordBatch有了数据Array和列描述Schema就可以构建RecordBatch了。注意列长度是必填参数且所有列长度必须一致std::shared_ptrarrow::RecordBatch rbatch; rbatch arrow::RecordBatch::Make(schema, days-length(), {days, months, years}); std::cout rbatch-ToString();RecordBatch::Make(schema, num_rows, columns)的三个参数分别是Schema、行数取自days-length()、列数组列表。ToString()会把整个表以可读文本形式打印出来方便验证结果。该段对应源码 arrow_example.cc 的(Doc section: RBatch)。构建 ChunkedArrayMaking a ChunkedArrayChunkedArray由若干个子Arraychunk组成设计动机包括拼接零拷贝合并数据时只需维护 chunk 列表无需复制元素便于并行处理不同 chunk 可分派到不同线程缓存友好每个 chunk 可以独立放入 CPU 缓存突破行数上限单个Array的行数受int32_t上限约束2,147,483,647 行而ChunkedArray无此限制。示例中我们复用前面已经构建好的days、months、years再补充几个新数组来凑足多个 chunk从而在不复制已有数据的前提下扩展它们。同样复用之前同类型的构建器int8_t days_raw2[5] {6, 12, 3, 30, 22}; ARROW_RETURN_NOT_OK(int8builder.AppendValues(days_raw2, 5)); std::shared_ptrarrow::Array days2; ARROW_ASSIGN_OR_RAISE(days2, int8builder.Finish()); int8_t months_raw2[5] {5, 4, 11, 3, 2}; ARROW_RETURN_NOT_OK(int8builder.AppendValues(months_raw2, 5)); std::shared_ptrarrow::Array months2; ARROW_ASSIGN_OR_RAISE(months2, int8builder.Finish()); int16_t years_raw2[5] {1980, 2001, 1915, 2020, 1996}; ARROW_RETURN_NOT_OK(int16builder.AppendValues(years_raw2, 5)); std::shared_ptrarrow::Array years2; ARROW_ASSIGN_OR_RAISE(years2, int16builder.Finish());该段对应源码 arrow_example.cc 的(Doc section: More Arrays)。为支持任意数量的子数组参与构造Arrow 提供了ArrayVector即std::vectorstd::shared_ptrArray的类型别名先把数组装进向量arrow::ArrayVector day_vecs{days, days2};再通过ChunkedArray的构造函数把向量封装为列式逻辑数组std::shared_ptrarrow::ChunkedArray day_chunks std::make_sharedarrow::ChunkedArray(day_vecs);对月和年重复相同流程arrow::ArrayVector month_vecs{months, months2}; std::shared_ptrarrow::ChunkedArray month_chunks std::make_sharedarrow::ChunkedArray(month_vecs); arrow::ArrayVector year_vecs{years, years2}; std::shared_ptrarrow::ChunkedArray year_chunks std::make_sharedarrow::ChunkedArray(year_vecs);这三段分别对应源码中的(Doc section: ArrayVector)与(Doc section: ChunkedArray Day)、(Doc section: ChunkedArray Month Year)arrow_example.cc。至此我们得到三个类型各异的ChunkedArray。构建 TableMaking a TableTable是ChunkedArray最典型的应用场景。与RecordBatch类似Table同样存储表格数据但不保证列内连续——因为它由ChunkedArray构成。这种分段结构带来与ChunkedArray相同的收益便于逻辑分块、并行化、缓存友好且能超过Array/RecordBatch的 2,147,483,647 行上限。对比前文可以发现Table的构造函数与RecordBatch几乎相同只是把行数参数放到了第 3 个位置并复用之前的Schemastd::shared_ptrarrow::Table table; table arrow::Table::Make(schema, {day_chunks, month_chunks, year_chunks}, 10); std::cout table-ToString();Table::Make(schema, columns, num_rows)columns是ChunkedArray列表num_rows为 10——即前文每个 chunk 5 行、共 2 个 chunk 的总行数。该段对应源码 arrow_example.cc 的(Doc section: Table)。Table类的完整接口可在 table.h 中查阅。收尾与完整代码在RunMain()末尾返回arrow::Status::OK()通知main()一切正常return arrow::Status::OK();至此你已成功构建了 Arrow 的四大基础数据结构。完整的可编译示例源码位于 cpp/examples/tutorial_examples/arrow_example.cc其内部通过(Doc section: ...)标记将各段代码与本文一一对应方便逐段对照阅读。编译与运行示例仓库为教程示例提供了完整的构建配套便于读者本地复现CMakeLists.txt声明ArrowTutorialExamples工程通过find_package(ArrowDataset)查找已安装的 Arrow以target_link_libraries(arrow_example PRIVATE Arrow::arrow_shared)链接共享库并启用-Wall -Wextra -Werror严格编译与 C20 标准build_arrow.sh先构建并安装 Arrow C 库启用 CSV、Dataset、Filesystem、Parquet 等组件build_example.sh以安装好的 Arrow 为依赖cmake配置示例工程后make编译出arrow_example等可执行文件run.sh串联以上两步并依次运行arrow_example、compute_example、file_access_example、dataset_example。典型流程为先按 build_arrow.sh 安装 Arrow底层对应 C 构建系统指南再执行cmakemake编译arrow_example最后运行该可执行文件观察ToString()输出的表格内容。这些步骤需要在具备 CMake最低 3.25与 C20 编译器如 GCC 11、Clang 14的环境中完成。小结本教程的核心收获可归纳为一张对照表数据结构内部组成列内连续追加/拼接代价行数上限Array单一连续缓冲区是需重建2,147,483,647ChunkedArray多个Array的列表否chunk 间不连续零拷贝无RecordBatch多个Array定长是需复制同ArrayTable多个ChunkedArray否零拷贝无在此基础上下一步可以学习如何将Table/RecordBatch写入文件或从文件读出参见 io_tutorial.rst以及在数组上执行计算内核参见 compute_tutorial.rst与读写多文件分区数据集参见 datasets_tutorial.rst。【免费下载链接】arrowApache Arrow is the universal columnar format and multi-language toolbox for fast data interchange and in-memory analytics项目地址: https://gitcode.com/GitHub_Trending/arrow3/arrow创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/14 9:34:17

Java开发常见错题解析与避坑指南

1. Java错题知识点概述作为一名Java开发者,在学习和工作中难免会遇到各种"坑"。3月25日这个时间节点,我整理了一批常见的Java错题知识点,这些内容涵盖了从基础语法到JVM原理的多个层面。这些错题不是简单的记忆点,而是真…

2026/9/14 9:34:17

基于JSP+SSM的大学生创业创新网站开发实践

1. 项目概述这个Java毕业设计项目选题"jspssm大学生创业创新网站"是一个典型的基于Java EE技术栈的Web应用开发实践。作为一名有多年Java开发经验的工程师,我认为这个选题非常适合计算机相关专业的毕业设计,因为它涵盖了从数据库设计到前端展示…

2026/9/14 9:34:17

MATLAB从零实现OFDM通信系统仿真与验证

简介:本资源是一份面向通信工程专业学生及MATLAB初学者的OFDM通信系统仿真实践材料,聚焦无线通信核心原理落地,解决OFDM概念抽象、编程实现难、信道建模不直观等学习痛点。压缩包仅含1个关键文件——ofdm.m主程序脚本(2KB&#xf…

2026/9/14 10:29:25

SpringBoot交友平台开发:毕业设计实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/14 10:29:25

DeepSeek V4.1 Flash部署实战:显存估算与vLLM/SGLang框架调优

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/14 10:29:25

AI论文写作工具测评与高效使用指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/14 2:17:50

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/14 0:03:22

KCF目标跟踪算法与OTB工程实现:毕业设计实战解析

简介:这是一份基于KCF核相关滤波算法、融合尺度池与抗遮挡处理的目标检测跟踪MATLAB完整源码,主要面向计算机相关专业准备毕业设计、课程设计或期末大作业的学生,也适合需要项目实战练习的初学者。源码在OTB数据集上完成验证,能够…

2026/9/14 0:03:22

语音情感识别实战:Keras实现LSTM、CNN、SVM与MLP多模型对比

简介:面向语音情感识别入门与进阶开发者,这份基于Keras的项目源码完整实现了LSTM、CNN、SVM、MLP四种模型,兼容Python3.8与Keras/TensorFlow2环境。压缩包内含49个文件,大小约70.31MB,主体包括Python脚本、yaml/json配…

2026/9/12 6:29:36

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/12 14:32:17

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/13 11:18:28

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码