使用PyArrow执行Substrait查询计划失败的问题求助
排查PyArrow执行Substrait计划时的ArrowNotImplementedError(Fetch转换问题)
问题背景
通过Ibis定义ratings和basics表结构并完成数据处理,编译生成Substrait查询计划topfilms.proto:
- DuckDB加载对应表并执行该计划,结果正常;
- PyArrow读取相同CSV表,实现
table_provider后调用run_query执行计划,触发错误:ArrowNotImplementedError: conversion to arrow::acero::Declaration from Substrait relation fetch
已排除PyArrow安装问题,基础示例可正常运行,转换为JSON格式计划后仍报错。
可能原因
- PyArrow对Substrait Fetch算子支持不完善:PyArrow的Acero执行引擎尚未完全实现Substrait Fetch算子(对应SQL的LIMIT/OFFSET)到
arrow::acero::Declaration的转换逻辑,而DuckDB的Substrait扩展对该算子兼容性更好。 - Ibis生成的Fetch算子变体不兼容:Ibis编译的Substrait计划中,Fetch算子的参数(如带OFFSET)或结构不符合PyArrow的预期,导致转换失败。
- PyArrow版本限制:部分旧版本PyArrow未实现Fetch算子的转换逻辑,即使基础示例能运行,特定算子仍存在支持遗漏。
排查步骤
- 解析Substrait计划内容
用substrait-text工具解析topfilms.proto,确认是否包含Fetch算子及参数:substrait-text read --format binary topfilms.proto - 简化计划测试
修改原Ibis查询,去掉LIMIT/OFFSET逻辑,重新生成Substrait计划并在PyArrow中执行。若成功,可定位问题出在Fetch算子。 - 验证PyArrow版本
检查当前PyArrow版本,建议升级到最新稳定版:import pyarrow print(pyarrow.__version__) - 对比基础示例计划
将PyArrow基础示例生成的Substrait计划与topfilms.proto对比,查看Fetch算子的结构差异。
解决建议
- 规避Fetch算子
先执行不带LIMIT/OFFSET的Substrait计划,再用PyArrow原生方法实现分页:# 执行无Fetch的计划 result = pyarrow.substrait.run_query(plan_no_fetch, table_provider) # 手动实现分页 paginated_result = result.slice(offset=10, length=20) - 调整Ibis查询逻辑
尝试仅用limit()而不使用offset(),或查看Ibis是否有配置参数可控制Substrait算子生成,避免生成PyArrow不支持的Fetch变体。 - 反馈PyArrow问题
若确认是PyArrow的功能遗漏,整理简化测试案例(含表结构、查询逻辑、Substrait计划)提交到PyArrow官方仓库,反馈Fetch算子转换的未实现问题。
内容的提问来源于stack exchange,提问作者Omri
相关产品推荐
相关产品推荐

