【发布时间】:2021-08-12 16:06:06
【问题描述】:
我是 TimescaleDB 和 Grafana 的新手,我使用的查询很慢。我认为我写的查询可以改进很多,但我不确定如何。任何建议表示赞赏。
我要下表:
create table key_value_data (
"time" timestamptz not null,
"context" varchar null,
"key" varchar[] not null,
"path" varchar not null,
"value" varchar not null
);
select create_hypertable('key_value_data', 'time');
然后我尝试为https://github.com/panodata/grafana-map-panel 选择数据。我试图解释我要在查询的 cmets 中实现的目标:
select
* -- this removes all rows with a null value in one of the columns, see where statement below
from
(
select
time_bucket_gapfill('5 seconds', "time") as "time", -- create time buckets of 5 seconds
"name", -- the name of the vessel
locf(last("lon", "time")) as "lon", -- last reported longitude in this bucket, if unknown in this bucket take the value of the previous bucket
locf(last("lat", "time")) as "lat", -- last reported latitude in this bucket, if unknown in this bucket take the value of the previous bucket
locf(last("sog", "time")) as "sog", -- last reported speed over ground in this bucket, if unknown in this bucket take the value of the previous bucket
locf(last("navstate", "time")) as "navstate" -- last reported navigation state in this bucket, if unknown in this bucket take the value of the previous bucket
from
(
select
"ais"."time",
case when "names"."name" is null then "ais"."context" else "names"."name" end as "name",
max(case when "ais"."path" = 'navigation.position.longitude' then "ais"."value"::numeric else null end) as "lon",
max(case when "ais"."path" = 'navigation.position.latitude' then "ais"."value"::numeric else null end) as "lat",
max(case when "ais"."path" = 'navigation.speedOverGround' then "ais"."value"::numeric * 3.6 else null end) as "sog",
max(case when "ais"."path" = 'navigation.state' then "ais"."value"::varchar else null end) as "navstate"
from
(
select
"time",
"context",
"path",
"value"
from
"key_value_data"
where
$__timeFilter("time") and
"path" in ('navigation.position.longitude', 'navigation.position.latitude', 'navigation.speedOverGround', 'navigation.state')
order by
1, 2, 3
) as "ais" -- this is a subquery to pivot the data, I cannot get the crosstab function working because I don't know how to insert the grafana $__timeFilter in the query text
inner join
(
select
"context",
last("value", "time") as "name"
from
"key_value_data" as "names"
where
$__timeFilter("time") and
"path" = 'name'
group by
1
) as "names" -- I made a separate query to retrieve the name of the vessel because this value is not injected in the table every x seconds but less frequent
on "ais"."context" = "names"."context"
group by
1, 2
) as "bucket"
where
$__timeFilter("time")
group by
1, 2
) as "result"
where
"lon" is not null and -- remove all rows with a null value in one of these columns
"lat" is not null and
"sog" is not null and
"navstate" is not null
我最终得到的查询既复杂又缓慢,我认为应该有更简单的方法来做到这一点。
Successfully run. Total query runtime: 465 msec.
106233 rows affected.
问题:
- 键值方法是在 key_value_data 表中存储数据的好方法吗?我现在不知道事先有哪些可用的钥匙,这取决于船上可用的传感器。
- 是否有更简单的方法来透视使用 Grafana 的
$__timeFilter函数的数据? - 是否需要透视数据,Grafana 是否可以在不透视的情况下处理键值数据?
【问题讨论】:
-
465 毫秒不是很快,但也没有那么慢。而您正在处理 106233 条记录,这可能是硬件问题。你能告诉我们这个查询的结果 van EXPLAIN(ANALYZE, BUFFERS, VERBOSE) 吗?
标签: sql postgresql time-series grafana timescaledb