为 InfluxDB IOx 设计 Parquet Catalog
作者:Paul Dix / 产品, 开发者
2021 年 5 月 21 日
导航至
我们需要为 InfluxDB IOx 采用或构建的功能之一是数据库目录。如果您还没有听说过它,InfluxDB IOx(发音为 eye-ox)是新的内存列式数据库,它使用对象存储进行持久化。我们正在将其构建为 InfluxDB 未来的核心。数据库目录通常包含数据库结构的定义,如模式和索引。对于使用对象存储进行持久化的系统,它们也可能包含其他信息,如文件(对象位置)和摘要统计信息。
SQL 标准指定了一种通过 information_schema 表访问目录的方法。IOx 支持这种获取数据库模式信息的方法。您可以在针对 IOx SQL REPL 中的 paulco_mydata 数据库执行的 show tables 命令的输出中看到它
paulco_mydata> show tables; +---------------+--------------------+---------------+------------+ | table_catalog | table_schema | table_name | table_type | +---------------+--------------------+---------------+------------+ | public | iox | cpu | BASE TABLE | | public | iox | disk | BASE TABLE | | public | iox | diskio | BASE TABLE | | public | iox | mem | BASE TABLE | | public | iox | processes | BASE TABLE | | public | iox | swap | BASE TABLE | | public | iox | system | BASE TABLE | | public | system | chunks | BASE TABLE | | public | system | columns | BASE TABLE | | public | system | chunk_columns | BASE TABLE | | public | system | operations | BASE TABLE | | public | information_schema | tables | VIEW | | public | information_schema | columns | VIEW | +---------------+--------------------+---------------+------------+ Returned 13 rows in 4.085615ms paulco_mydata>
虽然 IOx 支持这种更标准的获取模式信息的方法,但本文讨论的目录侧重于跟踪对象存储中存在的内容。我们需要一种有效的方法来跟踪 InfluxDB IOx 写入对象存储的 Parquet 文件的模式和统计信息。鉴于此,我们必须决定是设计我们自己的解决方案,还是采用其他项目中的标准。我们研究了 Apache Hive、Delta Lake 和 Apache Iceberg 作为潜在的实现方案。最终,我们决定实施我们自己的设计,在本文的其余部分,我将讨论该设计,并将其与其他设计进行一些比较。
我们需要通过目录实现来满足许多具体要求。首先也是最重要的,我们需要指向作为数据库一部分的 Parquet 文件列表的指针。但是,我们也希望支持软删除,让用户能够删除数据,但如果需要恢复,数据仍然可以保留一段时间。这意味着并非对象存储中的所有 Parquet 文件都是可查询集的一部分。
IOx 将用于优化性能的技巧之一是简单地避免评估数据库中尽可能多的数据。它通过对数据进行分区,然后在查询时根据查询修剪掉不相关的分区来实现这一点。之后,我们在相关的分区上执行查询,以尽快获得结果。为此,数据库需要知道各个分区以及其中文件存在的模式和摘要统计信息。如果没有目录,数据库将需要在启动时扫描所有 Parquet 文件并从中读取摘要数据。
InfluxDB IOx 还必须能够有效地跟踪数据库中的数千个表。IOx 用户可能有一个数据库,其中所有数据都进入一个宽表(可能用于跟踪用例),但他们也有其他数据库,其中数据将分布在许多表上(可能用于指标用例)。IOx 用户将能够在他们的模式中使用表来帮助他们逻辑地组织它,并对其进行分段以获得更好的查询性能。我们还需要所有这些表的模式,以便我们可以为查询进行快速查找和为写入进行验证。
最后,目录将需要支持删除的 tombstone 记录。这使得可以将删除立即反映在查询中,而无需实际重写 Parquet 文件本身。
所有这些要求加在一起,排除了使用 Hive、Delta Lake 或 Iceberg。这些标准也与 JVM 和/或基于 Hadoop 的生态系统紧密相关。IOx 必须可部署在边缘,因此我们需要一些轻量级且用 Rust 编写的东西。现有标准都没有成熟的 Rust 实现。
Hive 不支持软删除、原子提交或时间旅行。此外,它依赖于昂贵的 LIST 操作来构建其世界视图。
在 DataBricks 创建的 Delta Lake 更侧重于具有多个写入器的单表。IOx 的设计仔细地避免了对并发控制的需求,因为每个服务器都获得一个唯一的标识符,该标识符是对象存储中路径的第一部分。我们不需要支持多个写入器,因此我们不需要这种复杂性。
Iceberg 似乎是我们需求列表中最有希望的。但是,它侧重于单表用例,这将其排除在外。仅存在 Java 和 Python 实现,并且看起来实现规范需要相当多的复杂性。
因此,我们采用了我们自己的设计,该设计借鉴了这三个项目的许多概念。除了支持我们需要的功能外,我们还选择使用 Apache Thrift 中的 Parquet 元数据格式来保存有关元数据和统计信息的信息。这很方便,因为我们在直接读取目录或读取 Parquet 文件时将使用相同的代码路径。
我们在 GitHub 存储库中编写了有关 InfluxDB IOx 目录的更多详细信息。或者,如果您更喜欢观看演讲,设计目录的 Influx 工程师 Marco Neumann 上周在我们的月度技术讲座中就 InfluxDB IOx 目录设计 发表了演讲。如果您对 IOx 实现的这种细节感兴趣,请在每个月第二个星期三太平洋时间上午 8:00 加入我们的 月度 InfluxDB IOx 技术讲座。