Documentation

InfluxQL 内部结构

了解 InfluxQL 的实现,以理解结果是如何处理的以及如何创建高效的查询

查询生命周期

  1. InfluxQL 查询字符串被标记化,然后解析为抽象语法树 (AST)。这是查询本身的的代码表示形式。

  2. AST 被传递给 QueryExecutor,它将查询定向到适当的处理程序。例如,与元数据相关的查询由元服务执行,而 SELECT 语句由分片本身执行。

  3. 然后,查询引擎确定与 SELECT 语句的时间范围匹配的分片。从这些分片中,为语句中的每个字段创建迭代器。

  4. 迭代器被传递给发射器,发射器消耗它们并连接生成的结果点。发射器的工作是将简单的时间/值点转换为更复杂的结果对象,这些对象将返回给客户端。

理解迭代器

迭代器为循环遍历一组点提供了一个简单的接口。例如,这是一个 Float 点的迭代器

type FloatIterator interface {
    Next() *FloatPoint
}

这些迭代器通过 IteratorCreator 接口创建

type IteratorCreator interface {
    CreateIterator(opt *IteratorOptions) (Iterator, error)
}

IteratorOptions 提供有关字段选择、时间范围和维度的参数,迭代器创建器可以在规划迭代器时使用这些参数。IteratorCreator 接口在多个级别上使用,例如 ShardsShardEngine。这允许在适用的情况下执行优化,例如返回预先计算的 COUNT()

迭代器不仅仅用于从存储读取原始数据。迭代器可以组合,以便它们围绕输入迭代器提供额外的功能。例如,DistinctIterator 可以计算输入迭代器的每个时间窗口的不同值。或者,FillIterator 可以生成输入迭代器中缺少的其他点。

这种组合也非常适合聚合。例如,在以下 SQL 中,MEAN(value) 是一个 MeanIterator,它包装了来自底层分片的迭代器

SELECT MEAN(value) FROM cpu GROUP BY time(10m)

以下示例使用额外的迭代器 (DERIVATIVE()) 包装 MEAN(value),以确定均值的导数

SELECT DERIVATIVE(MEAN(value), 20m) FROM cpu GROUP BY time(10m)

游标

游标通过元组(时间、值)为单个序列(测量、标签集和字段)标识分片中的数据。游标遍历存储为日志结构合并树的数据,并处理跨级别的去重、已删除数据的墓碑以及合并缓存(预写日志)。游标按时间升序或降序对 (time, value) 元组进行排序。

例如,一个查询在 3 个分片上评估 1,000 个序列的一个字段,将构建至少 3,000 个游标(每个分片 1,000 个)。

辅助字段

由于 InfluxQL 允许用户使用选择器函数,例如 FIRST()LAST()MIN()MAX(),因此引擎必须提供一种方法,以便在返回所选点的同时返回相关数据。

让我们看一下以下查询

SELECT FIRST(value), host FROM cpu GROUP BY time(1h)

我们正在选择每小时发生的第一个 value,但我们也想检索与该点关联的 host。由于 Point 类型仅为效率指定单个类型化的 Value,因此我们将 host 推送到点的辅助字段中。这些辅助字段会附加到点,直到它传递到发射器,在那里字段被拆分到它们自己的迭代器。

内置迭代器

有许多辅助迭代器可以帮助我们构建查询

  • 合并迭代器 - 此迭代器将一个或多个迭代器组合成一个相同类型的新迭代器。此迭代器保证在开始下一个窗口之前输出窗口内的所有点,但不提供窗口内的排序保证。这允许快速访问不需要更强排序保证的聚合查询。

  • 排序合并迭代器 - 与 MergeIterator 类似,此迭代器将一个或多个迭代器组合成一个相同类型的新迭代器。但是,此迭代器保证每个点的时间顺序。这使得它比 MergeIterator 慢,但对于返回原始数据点的非聚合查询来说,这种排序保证是必需的。

  • 限制迭代器 - 此迭代器限制每个名称或标签组的点数。这是 LIMITOFFSET 语法的实现。

  • 填充迭代器 - 如果输入迭代器中缺少点,则此迭代器会注入额外的点。它可以提供 null 点、具有先前值的点或具有特定值的点。

  • 缓冲迭代器 - 此迭代器提供将点“取消读取”回缓冲区的功能,以便下次可以再次读取它。这广泛用于为窗口化提供前瞻。

  • 缩减迭代器 - 此迭代器为窗口中的每个点调用缩减函数。当窗口完成时,将输出该窗口的所有点。这用于简单的聚合函数,例如 COUNT()

  • 缩减切片迭代器 - 此迭代器首先收集窗口的所有点,然后一次性将它们全部传递给缩减函数。结果从迭代器返回。这用于聚合函数,例如 DERIVATIVE()

  • 转换迭代器 - 此迭代器为来自输入迭代器的每个点调用转换函数。这用于执行二进制表达式。

  • 去重迭代器 - 此迭代器仅输出唯一的点。由于它资源密集型,因此此迭代器仅用于小型查询,例如元查询语句。

调用迭代器

InfluxQL 中的函数调用在两个级别实现

  • 某些调用可以在多个层包装以提高效率。例如,COUNT() 可以在分片级别执行,然后多个 CountIterator 可以用另一个 CountIterator 包装,以计算所有分片的计数。这些迭代器可以使用 NewCallIterator() 创建。

  • 某些迭代器更复杂或需要在更高级别实现。例如,DERIVATIVE() 函数需要检索窗口的所有点,然后才能执行计算。此迭代器由引擎本身创建,并且永远不会被较低级别请求创建。


此页面是否对您有帮助?

感谢您的反馈!


Flux 的未来

Flux 即将进入维护模式。您可以继续像目前一样使用它,而无需对代码进行任何更改。

阅读更多

InfluxDB 3 开源版本现已公开发布 Alpha 版

InfluxDB 3 开源版本现已可用于 Alpha 测试,根据 MIT 或 Apache 2 许可获得许可。

我们正在发布两个产品作为 Alpha 版本的一部分。

InfluxDB 3 Core 是我们的全新开源产品。它是用于时间序列和事件数据的最新数据引擎。InfluxDB 3 Enterprise 是一个商业版本,它建立在 Core 的基础上,增加了历史查询功能、读取副本、高可用性、可扩展性和细粒度的安全性。

有关如何开始使用的更多信息,请查看