文档说明

使用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 字段转换为列。输出包括包含每个对应 _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 Clustered现已全面上市

新功能包括更快的查询性能和管理工具,推动了InfluxDB v3产品线的进步。InfluxDB Clustered现已全面上市。

InfluxDB v3性能和功能

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

了解新的v3增强功能


InfluxDB Clustered全面上市

InfluxDB Clustered现已全面上市,并为您在自管理的堆栈中提供InfluxDB v3的力量。

与我们谈谈InfluxDB Clustered