文档文档

使用 Flux 计算百分比

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

计算百分比

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

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

from(bucket: "example-bucket")
    |> 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 存储桶查询数据,并计算随时间推移使用的 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: "example-bucket")
    |> 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. 确保测量在同一存储桶中。
  2. 使用 filter() 包括来自两个测量的数据。
  3. 使用 group() 取消分组数据并返回单个表。
  4. 使用 pivot() 将字段透视为列。
  5. 使用 map() 重新映射行并执行百分比计算。
from(bucket: "example-bucket")
    |> 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 example_table",
)

t2 = from(bucket: "example-bucket")
    |> 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 Core 和 Enterprise

快速启动。更快扩展。

获取更新

InfluxDB 3 Core 是一个开源、高速、最近数据引擎,可实时收集和处理数据,并将其持久化到本地磁盘或对象存储。InfluxDB 3 Enterprise 构建在 Core 的基础上,增加了高可用性、读取副本、增强的安全性以及数据压缩,从而实现更快的查询和优化的存储。InfluxDB 3 Enterprise 的免费层可供非商业家庭或业余爱好者使用。

有关更多信息,请查看