文档文档

使用 Flux 计算百分比

此页面记录了早期版本的 InfluxDB OSS。InfluxDB OSS v2 是最新的稳定版本。请参阅等效的 InfluxDB v2 文档: 使用 Flux 计算百分比

从查询数据计算百分比是时间序列数据的常见用例。要在 Flux 中计算百分比,操作数必须在每一行中。使用 map() 重新映射行中的值并计算百分比。

要计算百分比

  1. 使用 from()range()filter() 查询操作数。
  2. 使用 pivot()join() 将操作数值对齐到行中。
  3. 使用 map() 将分子操作数值除以分母操作数值,然后乘以 100。

以下示例使用 pivot() 将操作数对齐到行中,因为 pivot() 在大多数情况下都有效,并且比 join() 性能更高。请参阅 Pivot vs join

from(bucket: "db/rp")
  |> range(start: -1h)
  |> filter(fn: (r) => r._measurement == "m1" and r._field =~ /field[1-2]/ )
  |> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value")
  |> map(fn: (r) => ({ r with _value: r.field1 / r.field2 * 100.0 }))

GPU 监控示例

以下示例查询来自 gpu-monitor bucket 的数据,并计算一段时间内使用的 GPU 内存百分比。数据包括以下内容

  • gpu 测量
  • mem_used 字段:已用 GPU 内存(字节)
  • mem_total 字段:总 GPU 内存(字节)

查询 mem_used 和 mem_total 字段

from(bucket: "gpu-monitor")
  |> range(start: 2020-01-01T00:00:00Z)
  |> filter(fn: (r) => r._measurement == "gpu" and r._field =~ /mem_/)
返回以下表流
_time_measurement_field_value
2020-01-01T00:00:00Zgpumem_used2517924577
2020-01-01T00:00:10Zgpumem_used2695091978
2020-01-01T00:00:20Zgpumem_used2576980377
2020-01-01T00:00:30Zgpumem_used3006477107
2020-01-01T00:00:40Zgpumem_used3543348019
2020-01-01T00:00:50Zgpumem_used4402341478

_time_measurement_field_value
2020-01-01T00:00:00Zgpumem_total8589934592
2020-01-01T00:00:10Zgpumem_total8589934592
2020-01-01T00:00:20Zgpumem_total8589934592
2020-01-01T00:00:30Zgpumem_total8589934592
2020-01-01T00:00:40Zgpumem_total8589934592
2020-01-01T00:00:50Zgpumem_total8589934592

将字段透视为列

使用 pivot()mem_usedmem_total 字段透视为列。输出包括 mem_usedmem_total 列,其中包含每个对应 _time 的值。

// ...
  |> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value")
返回以下内容
_time_measurementmem_usedmem_total
2020-01-01T00:00:00Zgpu25179245778589934592
2020-01-01T00:00:10Zgpu26950919788589934592
2020-01-01T00:00:20Zgpu25769803778589934592
2020-01-01T00:00:30Zgpu30064771078589934592
2020-01-01T00:00:40Zgpu35433480198589934592
2020-01-01T00:00:50Zgpu44023414788589934592

映射新值

现在,每一行都包含计算百分比所需的值。使用 map() 重新映射每一行中的值。将 mem_used 除以 mem_total,然后乘以 100 以返回百分比。

要返回包含小数点的精确浮点百分比值,以下示例将整数字段值转换为浮点数,然后乘以浮点值 (100.0)。

// ...
  |> map(fn: (r) => ({
    _time: r._time,
    _measurement: r._measurement,
    _field: "mem_used_percent",
    _value: float(v: r.mem_used) / float(v: r.mem_total) * 100.0
  }))
查询结果
_time_measurement_field_value
2020-01-01T00:00:00Zgpumem_used_percent29.31
2020-01-01T00:00:10Zgpumem_used_percent31.37
2020-01-01T00:00:20Zgpumem_used_percent30.00
2020-01-01T00:00:30Zgpumem_used_percent35.00
2020-01-01T00:00:40Zgpumem_used_percent41.25
2020-01-01T00:00:50Zgpumem_used_percent51.25

完整查询

from(bucket: "gpu-monitor")
  |> range(start: 2020-01-01T00:00:00Z)
  |> filter(fn: (r) => r._measurement == "gpu" and r._field =~ /mem_/ )
  |> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value")
  |> map(fn: (r) => ({
    _time: r._time,
    _measurement: r._measurement,
    _field: "mem_used_percent",
    _value: float(v: r.mem_used) / float(v: r.mem_total) * 100.0
  }))

示例

使用多个字段计算百分比

from(bucket: "db/rp")
  |> range(start: -1h)
  |> filter(fn: (r) => r._measurement == "example-measurement")
  |> filter(fn: (r) =>
    r._field == "used_system" or
    r._field == "used_user" or
    r._field == "total"
  )
  |> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value")
  |> map(fn: (r) => ({ r with
    _value: float(v: r.used_system + r.used_user) / float(v: r.total) * 100.0
  }))

使用多个测量计算百分比

  1. 确保测量在同一个 bucket 中。
  2. 使用 filter() 包含来自两个测量的数据。
  3. 使用 group() 取消分组数据并返回单个表。
  4. 使用 pivot() 将字段透视为列。
  5. 使用 map() 重新映射行并执行百分比计算。
from(bucket: "db/rp")
  |> range(start: -1h)
  |> filter(fn: (r) =>
    (r._measurement == "m1" or r._measurement == "m2") and
    (r._field == "field1" or r._field == "field2")    
  )
  |> group()
  |> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value")
  |> map(fn: (r) => ({ r with  _value: r.field1 / r.field2 * 100.0 }))

使用多个数据源计算百分比

import "sql"
import "influxdata/influxdb/secrets"

pgUser = secrets.get(key: "POSTGRES_USER")
pgPass = secrets.get(key: "POSTGRES_PASSWORD")
pgHost = secrets.get(key: "POSTGRES_HOST")

t1 = sql.from(
  driverName: "postgres",
  dataSourceName: "postgresql://${pgUser}:${pgPass}@${pgHost}",
  query:"SELECT id, name, available FROM exampleTable"
)

t2 = from(bucket: "db/rp")
  |> range(start: -1h)
  |> filter(fn: (r) =>
    r._measurement == "example-measurement" and
    r._field == "example-field"
  )

join(tables: {t1: t1, t2: t2}, on: ["id"])
  |> map(fn: (r) => ({ r with _value: r._value_t2 / r.available_t1 * 100.0 }))

此页面是否对您有帮助?

感谢您的反馈!


Flux 的未来

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

阅读更多

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

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

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

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

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