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标志,未来计划支持。