代表性面试主题

数据工程面试:如何验证 DataFusion 嵌套字段下推真的减少了扫描成本?

数据困难
Offer.cc 编辑团队发布 更新

题干

DataFusion 53 可以把嵌套字段访问下推到数据源。你如何设计查询、执行计划和基准,证明它减少了 I/O 与解码成本且不改变结果?

题目

DataFusion 53 可以把 get_field 这样的表达式下推到数据源。你如何设计查询、执行计划和基准,证明它减少了 I/O 与解码成本且不改变结果?

场景与适用边界

假设 Parquet 表含有宽大的 structs,查询只需要 s['label'] 并用 s['value'] 过滤。回答要覆盖批量扫描、统计信息、Null、Schema 演进和下推不生效时的回退;不要把“计划里出现 projection”直接当成端到端收益。

面试官考察点

考察你能否把优化拆成语义正确性、计划改写、数据源能力和可观测收益四层。DataFusion 53 将嵌套字段访问推近扫描节点,避免读取整个 struct;配置文档说明 enable_leaf_expression_pushdown 会把 get_field 从过滤、排序或连接表达式提取到更靠近叶节点的位置。

回答前可以先确认:

  • 数据源是否支持字段级投影,文件格式是否为 Parquet?
  • s['label']s['value'] 的类型、Null 语义及缺失字段如何定义?
  • 基线是关闭优化、旧版本 DataFusion,还是读取整个 struct 的手写查询?
  • 需要比较扫描字节、解码 CPU、峰值内存、延迟,还是云存储请求数?

30 秒回答框架

先给出带嵌套字段投影和过滤的 SQL;再说明如何对比优化前后逻辑计划、物理计划和 Parquet reader 的投影;最后用相同数据、缓存状态和并发度测量扫描字节、解码时间、峰值内存及结果校验,并说明何时回退。

分步骤深入解答

  1. 构造数据:生成相同分区、行组和统计信息的 Parquet 文件,控制 struct 宽度、Null 比例和字段选择性。
  2. 定义基线:固定 DataFusion 版本、线程数、对象存储延迟和缓存状态,分别运行关闭下推、读取完整 struct、只读叶字段三组查询。
  3. 验证计划:确认 get_field 位于扫描附近,投影只包含 ids.label 和过滤所需的 s.value;不能只看 SQL 文本。
  4. 观察数据源:记录 Parquet 读取列、行组裁剪、读取字节和解码批次,区分字段投影收益与谓词下推收益。
  5. 校验结果:对结果做排序后的哈希或逐行比较,覆盖缺失字段、Null、类型变化、空 struct 和重复行。
  6. 设定回退:数据源不支持字段下推、计划无法安全改写或收益低于阈值时,保留正确的完整读取路径并记录原因。

高质量示范回答

我会先用固定的 Parquet 数据集建立三组基线:读取完整 s、关闭 enable_leaf_expression_pushdown,以及开启优化并查询叶字段。查询如下:

sql
SELECT id, s['label']
FROM events
WHERE s['value'] > 150;

然后保存逻辑和物理计划,确认 get_field 被推到扫描节点附近,扫描投影不再包含整个 s。基准在冷缓存和热缓存各跑多轮,记录读取字节、对象存储请求、Parquet 解码 CPU、峰值内存、端到端延迟和输出行数。结果用稳定排序后的哈希与完整 struct 基线比较,专门覆盖 Null、缺失字段和新旧 Schema。若数据源不支持字段级投影,我会保留完整读取并发出指标,而不是为了计划好看牺牲正确性。上线前把扫描字节和结果哈希加入回归门槛。

常见错误

  • 只比较端到端延迟,没有控制缓存、并发和文件布局。
  • 把字段投影、谓词下推和行组裁剪混成一个收益数字。
  • 只验证正常值,忽略 Null、缺失字段和 Schema 演进。
  • 看到计划改写就宣布优化成功,没有检查 reader 实际读取的列和字节。
  • 下推失败时强行改写结果,缺少正确性优先的回退路径。

评估时看能否连接 SQL、计划、数据源和指标四层,给出可复现基线与结果校验,明确收益归因和回退条件。一般回答只说“投影下推会更快”,没有实验控制或正确性证据。

追问及应对

为什么读取叶字段可能仍然没有收益?

文件可能按行存储、struct 未被物理拆分、对象存储请求成为瓶颈,或数据源没有实现字段级投影。要看实际读取字节和解码时间,不能只看计划。

如果 s['value'] 大多为 Null,如何避免改变结果?

先固定 SQL 的 Null 语义和类型规则,用完整读取基线逐行比较;优化只能减少不需要的字段读取,不能把 Null 当成缺失或错误值。

Schema 新增嵌套字段后,旧文件怎么办?

读取器应按字段名和默认值解析旧文件,缺失字段保持定义的 Null 或默认语义;基准必须同时包含旧、新文件,并验证合并扫描结果。

面试作答要点

一句话总结

证明下推优化要同时验证计划位置、实际扫描、结果一致性和不可用时的安全回退。

公开来源

同类题目