如何在Julia中向GroupedDataFrame生成的Arrow.Table各分区追加数据?
问题描述
我有一个GroupedDataFrame GDF1,希望将其保存为每个子DataFrame作为单独分区的Arrow.Table,目前用Arrow.append实现。但我想在创建Arrow.Table后,向每个现有分区追加数据,而非新增分区。
直接用Arrow.append把新的GroupedDataFrame GDF2追加到现有Arrow.Table时,会生成额外分区,而不是往原分区里加数据。
当前代码
GDF1 = groupby(DataFrame(ID = [ "Eng1", "Eng2"] , Date = [Date(2023,4,10),Date(2023,4,10)], Time = [3.85, 4.13]), :ID) File = "oldfilepath" for i in GDF1 Arrow.append(File, i) end GDF2 = groupby(DataFrame(ID = [ "Eng1", "Eng2"] , Date = [Date(2023,4,12),Date(2023,4,12)], Time = [3.87, 4.14]), :ID) for i in GDF2 Arrow.append(File, i) end
执行结果
View = DataFrame(Arrow.Table(File)) 4×3 DataFrame Row │ ID Date Time │ String Date Float64 ─────┼───────────────────────────── 1 │ Eng1 2023-04-10 3.85 2 │ Eng2 2023-04-10 4.13 3 │ Eng1 2023-04-12 3.87 4 │ Eng2 2023-04-12 4.14
期望结果
保留初始2个分区,新数据追加到对应分区:
4×3 DataFrame Row │ ID Date Time │ String Date Float64 ─────┼───────────────────────────── 1 │ Eng1 2023-04-10 3.85 2 │ Eng1 2023-04-12 3.87 3 │ Eng2 2023-04-10 4.13 4 │ Eng2 2023-04-12 4.14
由于GDF1数据量极大,无法加载到内存合并GDF2后排序,请问能否在不创建新Arrow.Table的前提下更新各分区?求最优实现方法。
解决方案
核心思路
Arrow文件的分区是追加式写入的,默认Arrow.append只会在文件末尾新增分区,无法直接修改已有分区。要实现往对应分区追加数据,需要先按分组ID关联存储单元,后续定向追加。
最优实现:按分组ID单独存储分区文件
这种方式灵活且低风险,完全不需要加载全量数据到内存:
# 创建分区存储目录 mkpath("arrow_partitions") # 写入初始分组数据,每个分组对应独立Arrow文件 for g in GDF1 id = first(g.ID) Arrow.write("arrow_partitions/$(id).arrow", g) end # 追加新分组数据到对应文件 for g in GDF2 id = first(g.ID) Arrow.append("arrow_partitions/$(id).arrow", g) end # 按需读取所有分区合并为Arrow.Table(和单文件使用逻辑一致) table = Arrow.Table("arrow_partitions"; partitions=true) df = DataFrame(table)
- 每个分组的数据始终存储在单独文件中,后续追加直接定位到对应文件即可
- 读取时通过
partitions=true参数自动合并所有分区,体验和单Arrow文件一致
备选方案:修改单Arrow文件的分区(不推荐)
如果必须用单个Arrow文件,需要借助Arrow底层API定位分区偏移量并修改元数据,但操作复杂度高,且存在数据损坏风险,仅适合特殊场景:
- 读取现有Arrow文件的元数据,获取每个分区的偏移量和长度
- 定位目标分区的末尾位置,写入新数据
- 更新文件元数据中对应分区的长度信息
这种方式需要深入Arrow文件格式细节,不推荐作为常规方案。
注意事项
- 确保GDF1和GDF2的分组ID完全匹配,避免出现找不到对应分区的情况
- 若后续需要合并为单文件,可在低峰期执行合并操作,不影响实时追加流程
内容的提问来源于stack exchange,提问作者phntm
相关产品推荐
相关产品推荐

