InfluxQL 内部原理
InfluxDB 3 Core 处于公开 Alpha 版
InfluxDB 3 Core 处于公开 alpha 版,可用于测试和反馈,但不适用于生产环境使用。该产品和本文档均在开发中。我们欢迎并鼓励您提供关于 alpha 版体验的意见,并邀请您加入我们的公共频道以获取更新和分享反馈。
了解 InfluxQL 的实现,以理解结果是如何处理的以及如何创建高效的查询
查询生命周期
InfluxQL 查询字符串被标记化,然后解析为抽象语法树 (AST)。这是查询本身的代码表示。
AST 被传递给
QueryExecutor
,后者将查询定向到适当的处理程序。例如,与元数据相关的查询由元数据服务执行,而SELECT
语句则由分片本身执行。然后,查询引擎确定与
SELECT
语句的时间范围匹配的分片。从这些分片中,为语句中的每个字段创建迭代器。迭代器被传递给发射器,后者耗尽它们并连接结果点。发射器的任务是将简单的时间/值点转换为更复杂的结果对象,这些对象将返回给客户端。
理解迭代器
迭代器为循环访问一组点提供了一个简单的接口。例如,这是一个浮点数点的迭代器
type FloatIterator interface {
Next() *FloatPoint
}
这些迭代器通过 IteratorCreator
接口创建
type IteratorCreator interface {
CreateIterator(opt *IteratorOptions) (Iterator, error)
}
IteratorOptions
提供了关于字段选择、时间范围和维度的参数,迭代器创建器可以在规划迭代器时使用这些参数。IteratorCreator
接口在多个级别上使用,例如 Shards
、Shard
和 Engine
。这允许在适用时执行优化,例如返回预先计算的 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)
游标
游标通过分片以元组 (时间, 值) 的形式标识单个序列(测量名称、标签集和字段)的数据。游标遍历存储为日志结构合并树的数据,并处理跨级别的去重、已删除数据的墓碑标记以及合并缓存(预写日志)。游标按时间升序或降序对 (时间, 值)
元组进行排序。
例如,一个为 1,000 个序列在 3 个分片上评估一个字段的查询至少构造 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
慢,但非聚合查询(返回原始数据点)需要此排序保证。限制迭代器 - 此迭代器限制每个名称或标签组的点数。这是
LIMIT
和OFFSET
语法的实现。填充迭代器 - 此迭代器在输入迭代器中缺少点时注入额外的点。它可以提供
null
点、具有先前值的点或具有特定值的点。缓冲迭代器 - 此迭代器提供将点“取消读取”回缓冲区的功能,以便下次可以再次读取它。这广泛用于为窗口化提供前瞻。
规约迭代器 - 此迭代器为窗口中的每个点调用规约函数。当窗口完成时,则输出该窗口的所有点。这用于简单的聚合函数,例如
COUNT()
。规约切片迭代器 - 此迭代器首先收集窗口的所有点,然后一次性将它们全部传递给规约函数。结果从迭代器返回。这用于聚合函数,例如
DERIVATIVE()
。转换迭代器 - 此迭代器为来自输入迭代器的每个点调用转换函数。这用于执行二元表达式。
去重迭代器 - 此迭代器仅输出唯一点。由于它资源密集型,因此此迭代器仅用于小型查询,例如元数据查询语句。
调用迭代器
InfluxQL 中的函数调用在两个级别实现
某些调用可以在多个层包装以提高效率。例如,
COUNT()
可以在分片级别执行,然后多个CountIterator
可以用另一个CountIterator
包装,以计算所有分片的计数。这些迭代器可以使用NewCallIterator()
创建。某些迭代器更复杂或需要在更高级别实现。例如,
DERIVATIVE()
函数需要检索窗口的所有点,然后才能执行计算。此迭代器由引擎本身创建,永远不会被较低级别请求创建。
此页是否对您有帮助?
感谢您的反馈!
支持和反馈
感谢您成为我们社区的一份子!我们欢迎并鼓励您提供关于 InfluxDB 3 Core 和本文档的反馈和错误报告。要获得支持,请使用以下资源
拥有年度合同或支持合同的客户可以联系 InfluxData 支持。