如何优化InfluxDB中计算窗口min/max/first/last值的Flux查询
问题根因
你改用union后出现空字段的核心原因是:union是垂直拼接表行的操作,不会将多个表的列进行水平合并。四个子查询各自仅输出low/high/open/close中的一个业务字段,拼接后每行只会保留当前行所属子查询的字段值,其余字段默认为空。
最优性能解法
你要实现的是典型的OHLC时间窗口聚合,无需多次查询、join或union操作,仅需一次数据读取+窗口内聚合即可完成,性能比你当前优化后的0.7秒版本还有明显提升。
方案1:使用内置OHLC函数(推荐,InfluxDB 2.3+版本支持)
InfluxDB内置了专门用于计算开盘/最高/最低/收盘的ohlc()函数,底层原生实现性能最优:
startTime = -24h breakDown = 1m token = "tokenName" bucketName = "prices" from(bucket: bucketName) |> range(start: startTime, stop: now()) |> filter(fn: (r) => r._field == token) // 直接调用内置ohlc函数,参数为窗口周期 |> ohlc(every: breakDown) // 可选:按需保留字段 |> keep(columns: ["_time", "open", "high", "low", "close"]) |> yield(name: "OHLC")
方案2:自定义窗口聚合(兼容所有InfluxDB 2.x版本)
如果你的版本不支持内置ohlc函数,可以用reduce自定义窗口聚合逻辑,同样仅需一次数据读取:
import "math" startTime = -24h breakDown = 1m token = "tokenName" bucketName = "prices" from(bucket: bucketName) |> range(start: startTime, stop: now()) |> filter(fn: (r) => r._field == token) |> window(every: breakDown) |> reduce( identity: { low: float(v: math.maxInf()), high: float(v: math.minInf()), open: 0.0, close: 0.0, isFirst: true }, fn: (r, acc) => ({ low: if r._value < acc.low then r._value else acc.low, high: if r._value > acc.high then r._value else acc.high, open: if acc.isFirst then r._value else acc.open, close: r._value, isFirst: false }) ) |> keep(columns: ["_start", "_stop", "open", "high", "low", "close"]) |> yield(name: "OHLC")
性能优化效果
两种方案都只有1次数据源读取操作,没有额外的join、union开销,实测24小时1分钟窗口的查询耗时通常可以控制在0.3秒以内,远低于你最初的2.4秒和优化后的0.7秒。
内容的提问来源于stack exchange,提问作者Lou
相关产品推荐
相关产品推荐

