文档文档

使用 Flux 计算百分比

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

计算百分比

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

以下示例使用 pivot() 将操作数对齐到行中,因为 pivot() 在大多数情况下都有效,并且比 join() 性能更好。请参阅 Pivot 与 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 字段转换为列。输出包括包含每个对应 _time 的值的 mem_usedmem_total 列。

// ...
    |> 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 v3 增强功能和 InfluxDB 集群版现在已正式发布

新功能包括更快的查询性能和管理工具,InfluxDB v3 产品线现在已正式发布。

InfluxDB v3 性能和功能

InfluxDB v3 产品线在查询性能方面取得了显著提升,并提供了新的管理工具。这些增强包括一个操作仪表板来监控您的 InfluxDB 集群的健康状况,InfluxDB Cloud Dedicated 中的单点登录(SSO)支持,以及用于令牌和数据库的新管理 API。

了解新的 v3 增强功能


InfluxDB 集群版已全面上市

InfluxDB 集群版现已全面上市,为您在自管理的堆栈中带来 InfluxDB v3 的强大功能。

咨询 InfluxDB 集群版

由 TSM 驱动的 InfluxDB Cloud