为 InfluxDB IOx 设计 Parquet 目录

导航至

为了InfluxDB IOx,我们需要采用或构建一个数据库目录。如果您还没有听说过,InfluxDB IOx(发音为eye-ox)是一个新的内存列式数据库,使用对象存储进行持久化。我们正在将其构建为InfluxDB的未来核心。数据库目录通常包含数据库结构的定义,如模式(schema)和索引。对于使用对象存储进行持久化的系统,它们可能还包含其他信息,如文件(对象位置)和汇总统计信息。

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 HiveDelta LakeApache Iceberg作为潜在的实施方案。最终,我们决定实施自己的设计,在本文的其余部分,我将讨论该设计并与其他设计进行比较。

我们需要用目录实现来满足一系列具体要求。首先,我们需要指向数据库中Parquet文件列表的指针。然而,我们也希望支持软删除,使用户能够删除数据,但如果有需要恢复,它仍然存在一段时间。这意味着不是所有对象存储中的Parquet文件都是可查询集合的一部分。

IOx将使用的一种优化性能的技巧是尽可能避免评估数据库中的大部分数据。它通过分区数据,然后在查询时根据查询修剪不相关的分区来实现。之后,我们在相关的分区上执行查询,以尽可能快地返回结果。为此,数据库需要知道各个分区及其内部文件中存在的内容的架构和汇总统计信息。没有目录,数据库在启动时需要扫描所有Parquet文件并从它们中读取汇总数据。

InfluxDB IOx还必须能够高效地跟踪数据库中的成千上万的表。IOx用户可能有一个所有数据都进入一个宽表(可能用于跟踪用例)的数据库,但他们也可能有其他数据将分布在许多表中的数据库(可能用于度量用例)。IOx用户将能够使用模式中的表来帮助他们逻辑上组织它们以及分割它们以获得更好的查询性能。我们还需要所有这些表的架构,以便我们可以为查询进行快速查找和验证写入。

最后,目录需要支持墓碑记录以支持删除操作。这使得删除操作能够在查询中立即反映出来,而无需实际重写Parquet文件。

所有这些要求加在一起,排除了使用Hive、Delta Lake或Iceberg。这些标准也与JVM和/或基于Hadoop的生态系统密切相关。IOx必须在边缘部署,因此我们需要一个轻量级且用Rust编写的解决方案。现有的所有标准都没有成熟的Rust实现。

Hive不支持软删除、原子提交或时间旅行。此外,它依赖于昂贵的LIST操作来构建其对世界的视图。

Delta Lake是由DataBricks创建的,更专注于单个表和多作者。IOx的设计仔细避免了并发控制的需求,因为每个服务器都有一个唯一的标识符,这是对象存储路径的第一部分。我们没有支持多作者的需求,因此不需要这种复杂性。

Iceberg在我们的需求列表中似乎最有前景。然而,它专注于单个表的用例,这将其排除在外。只有Java和Python实现,而且看起来实现该规范相当复杂。

因此,我们采用了自己的设计,借鉴了这三个项目的许多概念。除了支持我们需要的功能外,我们还选择使用Apache Thrift的Parquet元数据格式来保持元数据和统计信息。这是因为当读取目录或直接读取Parquet文件时,我们会使用相同的代码路径。

有关InfluxDB IOx目录的更多详细信息,请参阅GitHub仓库中的InfluxDB IOx目录。或者,如果您更喜欢观看演讲,上周我们的月度技术研讨会上,设计了目录的Influx工程师Marco Neumann发表了一次关于InfluxDB IOx目录设计的演讲。如果您对IOx实现的这种细节感兴趣,请加入我们每月第二个周三上午8点的InfluxDB IOx技术研讨会