Grafana 是一个非常流行的开源数据可视化和监控平台,它与 TimescaleDB 集成得非常好,因为 TimescaleDB 是基于 PostgreSQL 的,而 Grafana 对 PostgreSQL 有原生的数据源支持。
下面我将介绍如何在 Grafana 中配置 TimescaleDB 数据源,并演示如何创建一个简单的 Panel 来可视化你的 FactPowerReadings
表中的数据。
1. Grafana 与 TimescaleDB (PostgreSQL) 集成步骤
Grafana 通过其 PostgreSQL 数据源插件与 TimescaleDB 通信。由于 TimescaleDB 是 PostgreSQL 的扩展,Grafana 的 PostgreSQL 数据源可以直接连接到 TimescaleDB 数据库。
步骤如下:
http://localhost:3000
。admin
和密码 admin
登录。首次登录会提示修改密码。Data sources
。Add data source
按钮。PostgreSQL
。TimescaleDB-Telemetry
。localhost:5432
(使用你在 Perl 脚本中配置的 $db_host:$db_port
)。telemetry
(使用你在 Perl 脚本中配置的 $db_name
)。ops
(使用你在 Perl 脚本中配置的 $db_user
)。$db_pass
)。disable
。TimescaleDB
选项。这会启用 TimescaleDB 特有的一些优化,比如 time_bucket
函数的自动补全和支持。Save & test
按钮。如果连接成功,会显示 “Database Connection OK”。如果失败,请检查数据库地址、端口、用户名、密码、数据库名以及防火墙设置。2. 创建一个 Panel 演示
现在我们来创建一个 Panel,例如展示一段时间内所有 FTU 的总平均有功功率 (ActivePower_Total
) 随时间变化的折线图。
创建新的 Dashboard (可选但推荐):
New dashboard
。Add a new panel
。配置 Panel:
Graph
(图表)。TimescaleDB-Telemetry
)。TimescaleDB
。SQL 查询:
SQL
SELECT
time_bucket('$__interval', "ReadingTimestamp") AS time,
AVG("ActivePower_Total") AS value
FROM
FactPowerReadings
WHERE
$__timeFilter("ReadingTimestamp")
GROUP BY
1 -- Group by the first selected column (time)
ORDER BY
time
解释一下这个查询:
SELECT time_bucket('$__interval', "ReadingTimestamp") AS time
:
time_bucket
是 TimescaleDB 提供的一个函数,用于将时间戳按指定的时间间隔进行分组。'$__interval'
是 Grafana 提供的一个内置变量,它会根据你在 Dashboard 右上角选择的时间范围和图表的宽度,自动计算出一个合适的时间间隔(例如 1分钟、5分钟、1小时等),用于数据的聚合。这使得图表在不同时间范围下显示的数据密度是合理的。"ReadingTimestamp"
是你的事实表中的时间列。AS time
是必须的!Grafana 的 Graph Panel 要求时间序列查询的结果集包含一个名为 time
的列(通常是时间戳或时间桶的起始时间),一个名为 value
的列(表示在该时间点或时间桶内的度量值)。AVG("ActivePower_Total") AS value
: 计算每个时间桶内的 ActivePower_Total
的平均值,并将其命名为 value
,符合 Grafana 的要求。你也可以使用 SUM
, MAX
, MIN
, COUNT
等聚合函数。FROM FactPowerReadings
: 从你的事实表中获取数据。WHERE $__timeFilter("ReadingTimestamp")
:
$__timeFilter("ReadingTimestamp")
是 Grafana 提供的另一个非常重要的内置变量。它会根据你在 Dashboard 右上角选择的全局时间范围,自动生成一个 WHERE "ReadingTimestamp" BETWEEN '...' AND '...'
这样的 SQL 子句,从而只查询指定时间范围内的数据。所有时序相关的查询都应该包含这个条件。GROUP BY 1
: 根据 SELECT
语句中的第一列进行分组,这里就是按 time_bucket
生成的时间桶进行分组。ORDER BY time
: 按照时间顺序排序结果,这对于绘制时间序列图是必要的。预览和调整: 在你输入查询后,Grafana 会自动执行并显示预览图。如果数据插入成功并且时间范围选对了,你应该能看到一条折线图。
配置可视化选项: 在 Panel 编辑器的右侧,你可以调整各种可视化选项,例如:
保存 Panel 和 Dashboard: 点击右上角的 Apply
按钮保存 Panel。然后点击 Dashboard 顶部的保存图标保存整个 Dashboard。
添加按 FTU 分组或过滤
如果你想看每个 FTU 的功率曲线,或者只看某个特定 FTU 的数据,可以修改查询并使用 Grafana 变量。
示例:按 FTU 分组并显示多条曲线
SQL
SELECT
time_bucket('$__interval', "ReadingTimestamp") AS time,
AVG("ActivePower_Total") AS value,
"FTUKey" AS metric -- 将 FTUKey 作为 metric,Grafana 会为每个 FTUKey 绘制一条曲线
FROM
FactPowerReadings
WHERE
$__timeFilter("ReadingTimestamp")
GROUP BY
1, "FTUKey" -- 同时按时间桶和 FTUKey 分组
ORDER BY
time
在这个查询中,我们将 FTUKey
选出来并命名为 metric
。Grafana 的 Graph Panel 会识别 metric
列,并为 metric
列的每一个不同的值绘制一条单独的折线。
示例:使用 Grafana 变量过滤特定 FTU
创建变量: 在 Dashboard 设置中 (齿轮图标),点击 Variables
。添加一个新变量,例如命名为 ftu_key
。
Query
SELECT "FTUKey" FROM DimFTU WHERE "IsCurrent" = TRUE ORDER BY "FTUKey";
修改 Panel 查询: 在你的 Graph Panel 查询中,使用 $ftu_key
变量:
SQL
SELECT
time_bucket('$__interval', "ReadingTimestamp") AS time,
AVG("ActivePower_Total") AS value
FROM
FactPowerReadings
WHERE
$__timeFilter("ReadingTimestamp") AND "FTUKey" = $ftu_key -- 使用变量过滤
GROUP BY
1
ORDER BY
time
现在,图表将只显示你在变量下拉菜单中选择的那个 FTU 的数据。
使用维度表信息 (例如 FTU_ID 或 Substation)
如果你想在图例中显示 FTU 的 ID (DimFTU.FTU_ID
) 而不是数字的 Key,或者想按变电站 (DimXTU.Substation
) 过滤,你需要使用 SQL JOIN。
示例:按 Substation 过滤,显示 FTU_ID 作为图例
假设你已经创建了一个名为 $substation
的 Grafana 变量来选择变电站。
SQL
SELECT
time_bucket('$__interval', fr.ReadingTimestamp) AS time,
AVG(fr."ActivePower_Total") AS value,
df.ftu_id AS metric -- 使用 FTU_ID 作为图例
FROM
FactPowerReadings fr
JOIN DimFTU df ON fr.FTUKey = df.FTUKey -- 连接 DimFTU
JOIN DimXTU dx ON df.XTUKey = dx.XTUKey -- 连接 DimXTU
WHERE
$__timeFilter(fr.ReadingTimestamp) AND dx.substation = $substation -- 按变电站过滤
GROUP BY
1, df.ftu_id -- 按时间桶和 FTU_ID 分组
ORDER BY
time
这个查询稍微复杂一些,通过 JOIN 获取维度信息,并用于过滤和作为多条曲线的标识 (metric
)。
总结:
Grafana 与 TimescaleDB 的集成非常顺畅,主要依赖于 Grafana 的 PostgreSQL 数据源和 TimescaleDB 的时序函数 (如 time_bucket
)。核心是编写正确的 SQL 查询,利用 Grafana 的内置变量 ($__timeFilter
, $__interval
) 来实现动态时间范围和自动聚合,并根据需要使用 SQL JOIN 和 Grafana 变量来结合维度信息进行过滤和分组可视化。