跳到主要内容

Avro 扩展

avro 扩展使 Goose 能够读取 Apache Avro 文件。

read_avro 函数

该扩展新增了一个 Goose 函数 read_avro。用法如下:

FROM read_avro('⟨some_file⟩.avro');

该函数会将 Avro 文件内容暴露为 Goose 表。随后可使用任意 SQL 语法继续转换该表。

文件 IO

read_avro 函数已集成到 Goose 的文件系统抽象中,这意味着你可以直接从 HTTP 或 S3 等来源读取 Avro 文件。例如:

FROM read_avro('s3://⟨your-bucket⟩/⟨some_file⟩.avro');

通常可以“直接工作”。

你也可以在一次读取中通过 glob 匹配多个文件,或向函数传入文件列表:

FROM read_avro('some_file_*.avro');
FROM read_avro(['some_file_1.avro', 'some_file_2.avro']);

如果文件名中包含有价值信息(这种情况其实很常见),可以向 read_avro 传入 filename 参数:

FROM read_avro('some_file_*.avro', filename=true);

这样结果集中会多出一列,包含 Avro 文件的实际文件名。

Schema 转换

该扩展会自动将 Avro Schema 转换为 Goose schema。除 Goose 不支持的递归类型定义外,所有 Avro 类型都可转换。

类型映射整体较直接,但 Avro 对 NULL 的处理方式较“特殊”。与其他系统不同,Avro 不把 NULL 视作如 INTEGER 这类类型的可选值,而是将其表示为“实际类型 + 特殊 NULL 类型”的 union。Goose 不同,任意值都可以是 NULL。当然 Goose 也支持 UNION 类型,但直接映射会让使用变得繁琐。

该扩展会在可能时对 Avro schema 进行简化:任意类型与 special null type 组成的 Avro union 会被简化为非空类型本身。例如,Avro 中 ["int","null"] 会转换成 Goose INTEGER(只是该列有时为 NULL)。同理,只包含单一类型的 Avro union 会直接转换为该类型。例如 ["int"] 也会变成 Goose INTEGER

该扩展还会对 Avro schema 做“扁平化”处理。Avro 将表定义为根级别的 record 字段,这与 Goose 的 STRUCT 字段等价。为便于使用,扩展会把单个顶层 record 的各项转成顶层列。

实现

在内部实现上,该扩展使用“官方” Apache Avro C API,并做了少量补丁以支持从内存读取 Avro 文件。

限制与未来计划

  • 目前扩展在读取单个(大)Avro 文件或文件列表时都未利用并行能力。后者的并行支持已在路线图中。
  • 当前还不支持 projection 或 filter pushdown,后续计划支持。
  • 由于 Avro 库依赖问题,当前不支持 Goose 的 Wasm 和 Windows-MinGW 构建(又是依赖问题)。后续会修复。
  • 如上所述,Goose 无法表达 Avro 的递归类型定义,这一点大概率不会改变。
  • 目前不支持用户提供独立 Avro schema 文件。此行为预计也不会改变,我们见到的 Avro 文件基本都内嵌 schema。
  • 目前不支持 Goose 其他 reader 支持的 union_by_name 标志,未来计划支持。