使用 Flux 计算百分比
从查询数据中计算百分比是时间序列数据的一个常见用例。要在 Flux 中计算百分比,操作数必须在每一行中。使用 map()
重新映射行中的值并计算百分比。
计算百分比
- 使用
from()
、range()
和filter()
查询操作数。 - 使用
pivot()
或join()
将操作数值对齐到行中。 - 使用
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:00Z | gpu | mem_used | 2517924577 |
2020-01-01T00:00:10Z | gpu | mem_used | 2695091978 |
2020-01-01T00:00:20Z | gpu | mem_used | 2576980377 |
2020-01-01T00:00:30Z | gpu | mem_used | 3006477107 |
2020-01-01T00:00:40Z | gpu | mem_used | 3543348019 |
2020-01-01T00:00:50Z | gpu | mem_used | 4402341478 |
_time | _measurement | _field | _value |
---|---|---|---|
2020-01-01T00:00:00Z | gpu | mem_total | 8589934592 |
2020-01-01T00:00:10Z | gpu | mem_total | 8589934592 |
2020-01-01T00:00:20Z | gpu | mem_total | 8589934592 |
2020-01-01T00:00:30Z | gpu | mem_total | 8589934592 |
2020-01-01T00:00:40Z | gpu | mem_total | 8589934592 |
2020-01-01T00:00:50Z | gpu | mem_total | 8589934592 |
将字段转换为列
使用 pivot()
将 mem_used
和 mem_total
字段转换为列。输出包括包含每个对应 _time
的值的 mem_used
和 mem_total
列。
// ...
|> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value")
返回以下内容
_time | _measurement | mem_used | mem_total |
---|---|---|---|
2020-01-01T00:00:00Z | gpu | 2517924577 | 8589934592 |
2020-01-01T00:00:10Z | gpu | 2695091978 | 8589934592 |
2020-01-01T00:00:20Z | gpu | 2576980377 | 8589934592 |
2020-01-01T00:00:30Z | gpu | 3006477107 | 8589934592 |
2020-01-01T00:00:40Z | gpu | 3543348019 | 8589934592 |
2020-01-01T00:00:50Z | gpu | 4402341478 | 8589934592 |
映射新值
现在每行都包含计算百分比所需的值。使用 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:00Z | gpu | mem_used_percent | 29.31 |
2020-01-01T00:00:10Z | gpu | mem_used_percent | 31.37 |
2020-01-01T00:00:20Z | gpu | mem_used_percent | 30.00 |
2020-01-01T00:00:30Z | gpu | mem_used_percent | 35.00 |
2020-01-01T00:00:40Z | gpu | mem_used_percent | 41.25 |
2020-01-01T00:00:50Z | gpu | mem_used_percent | 51.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
}),
)
使用多个测量值计算百分比
- 确保测量值在相同的桶中。
- 使用
filter()
包含来自两个测量值的数据。 - 使用
group()
解组数据并返回一个单表。 - 使用
pivot()
将字段旋转到列中。 - 使用
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}))
这个页面有用吗?
感谢您的反馈!