文档文档

InfluxQL 内部机制

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

查询生命周期

  1. InfluxQL 查询字符串被分词,然后解析成抽象语法树 (AST)。这是查询本身的源代码表示。

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

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

  4. 迭代器被传递给发射器 (emitter),发射器会逐个读取它们并连接结果点。发射器的任务是将简单的时间/值点转换为返回给客户端的更复杂的结果对象。

理解迭代器

迭代器提供了一个简单的接口来循环遍历一组点。例如,这是一个 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)

游标

游标 (cursor) 通过分片以 (时间, 值) 元组的形式标识单个序列 (measurement, tag set 和 field) 的数据。游标遍历存储在日志结构合并树 (log-structured merge-tree) 中的数据,并处理跨级别的去重、已删除数据的墓碑以及合并缓存 (写时日志)。游标按时间升序或降序对 (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 推入该点的辅助字段。这些辅助字段会附加到点上,直到传递给发射器,在那里字段会被分离成自己的迭代器。

内置迭代器

有许多帮助迭代器允许我们构建查询。

  • Merge Iterator - 此迭代器将一个或多个迭代器合并成一个新的相同类型的迭代器。此迭代器保证在一个窗口内的所有点都会在开始下一个窗口之前输出,但不对窗口内的点排序。这使得不需要更强排序保证的聚合查询可以快速访问。

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

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

  • Fill Iterator - 如果输入迭代器缺少点,此迭代器将注入额外的点。它可以提供 null 点、带有前一个值的点或带有特定值的点。

  • Buffered Iterator - 此迭代器提供了将点“反读”回缓冲区,以便下次可以再次读取。这被广泛用于为窗口化提供前瞻性。

  • Reduce Iterator - 此迭代器为窗口中的每个点调用一个归约函数。当窗口完成时,该窗口的所有点都会被输出。这用于简单的聚合函数,如 COUNT()

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

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

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

调用迭代器

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

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

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


此页面是否有帮助?

感谢您的反馈!


InfluxDB 3.8 新特性

InfluxDB 3.8 和 InfluxDB 3 Explorer 1.6 的主要增强功能。

查看博客文章

InfluxDB 3.8 现已适用于 Core 和 Enterprise 版本,同时发布了 InfluxDB 3 Explorer UI 的 1.6 版本。本次发布着重于操作成熟度,以及如何更轻松地部署、管理和可靠地运行 InfluxDB。

更多信息,请查看

InfluxDB Docker 的 latest 标签将指向 InfluxDB 3 Core

在 **2026 年 2 月 3 日**,InfluxDB Docker 镜像的 latest 标签将指向 InfluxDB 3 Core。为避免意外升级,请在您的 Docker 部署中使用特定的版本标签。

如果使用 Docker 来安装和运行 InfluxDB,latest 标签将指向 InfluxDB 3 Core。为避免意外升级,请在您的 Docker 部署中使用特定的版本标签。例如,如果使用 Docker 运行 InfluxDB v2,请将 latest 版本标签替换为 Docker pull 命令中的特定版本标签 — 例如

docker pull influxdb:2