You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于arrow::ListArray::offsets()含零及偏移量使用的技术问询

C++读取含浮点型列表的Parquet文件时遇到的偏移量异常问题

问题重现步骤

  • 通过Python(Polars+PyArrow)生成包含10行浮点型列表数据的测试Parquet文件
  • 使用C++ Arrow库读取该文件时,发现arrow::ListArray::offsets()返回的偏移量列表中穿插零值
  • 按常规示例调用value_offset(i)会导致程序崩溃,改用value_offset(2*i)才能正确读取数据

技术疑问

  1. 为何偏移量列表中会穿插零值?
  2. 为何文档说明偏移量数量为num_rows+1,但实际需访问到2*num_rows才能获取全部数据?
  3. 该现象是否为Arrow+Parquet的固定表现?十万行级数据是否仍遵循此模式?

问题解答

1. 偏移量列表穿插零值的原因

这是因为你错误读取了非偏移量的内存数据,大概率是混淆了ListArray的偏移量数组和有效性位图的存储。当你用Polars/PyArrow生成可空列表列时,Arrow会为该列额外维护一个有效性位图(标记每行是否为空值),如果你的C++代码没有通过正确API单独提取偏移量数组,而是直接读取了列的全部底层buffer,就会把位图的二进制零值当成偏移量的一部分,出现穿插零值的假象。

另外,如果某行是空值(而非空列表),Arrow会通过有效性位图标记,而非修改偏移量;但如果你误将位图数据混入偏移量读取,就会看到无意义的零值。

2. 偏移量数量与文档不符的原因

文档说明的num_rows+1是完全正确的,你需要访问到2*num_rows才能获取数据,本质是读取范围错误:你把有效性位图的长度也算进了偏移量数组的长度里。比如10行的ListArray,偏移量数组长度是11(10+1),而有效性位图按字节对齐后可能占用10字节左右,如果你把这两部分数据合并读取,就会误以为偏移量数组长度接近20,进而需要访问到2*num_rows。

3. 是否为固定表现及大数据量情况

这不是Arrow+Parquet的固定表现,完全是读取逻辑错误导致的。十万行数据下,只要正确使用Arrow C++的API读取偏移量,就不会出现这种问题。

正确的读取示例代码:

// 假设已读取到arrow::Array类型的列数据
auto list_array = std::static_pointer_cast<arrow::ListArray>(column_data);
// 获取正确的偏移量数组(注意类型为Int32Array或Int64Array)
auto offsets = std::static_pointer_cast<arrow::Int32Array>(list_array->offsets());
// 遍历每行数据
for (int64_t i = 0; i < list_array->length(); ++i) {
    // 检查当前行是否为有效非空行
    if (!list_array->IsValid(i)) {
        // 处理空值逻辑
        continue;
    }
    int32_t start = offsets->Value(i);
    int32_t end = offsets->Value(i+1);
    // 获取列表元素数组
    auto values = std::static_pointer_cast<arrow::FloatArray>(list_array->values());
    // 遍历当前行的所有元素
    for (int32_t j = start; j < end; ++j) {
        float val = values->Value(j);
        // 处理元素逻辑
    }
}

同时建议检查Python生成代码,确保列表列类型为非可空(如Polars中的List(f64)而非Optional[List(f64)]),这样Parquet写入时不会生成有效性位图,能进一步简化读取逻辑。

内容的提问来源于stack exchange,提问作者vinnewbie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 01:52:09