暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

如何使用PostgreSQL可视化时间推移?

原创 小小亮 2020-08-17
2015

image.png

问题:随着时间的推移比较指标(又称时移)

当我们进行实时监控或历史分析时,我们经常想在视觉上将指标NOW的值与X天,周,小时或几个月前的值进行比较(换句话说,我们希望将其比较在当前时间到其值的值时移的一个或多个时间间隔前)。

这被称为时移:将指标与其自身进行比较,但使用不同的时间段。

这在DevOps,IoT和用户行为分析场景中尤为常见,在这种情况下,我们想了解诸如上下波动之类的事情是季节性的还是新事物的结果,以及许多其他问题,需要我们分析如何某些指标会随着时间而变化。

例如,以监视出租车为例。在任何一天,我们可能会问类似的问题:今天的乘车活动与过去三天的活动相比如何?或者,本周五的乘车活动与上周的周五相比如何?那前一周呢?还是去年同期?这些关于出租车的问题可以轻松地应用于我们的网站正常运行时间指标,CPU利用率等等。

回答这些问题的一种(痛苦的)方式可能是为每个时间间隔创建单独的图表,然后手动对它们进行肉眼比较。但是,这不是很有效,手动比较可能会给您带来麻烦。

image.png
两张单独的图表显示了2016年1月连续几周的游乐设施

比较在2016年1月的第1周和第2周乘坐的出租车的图表。请注意比较两个图表之间的乘车活动有多么困难。

解决方案:使用PostgreSQL LATERAL JOIN

更好的方法是将所有趋势线(当前活动和时移活动都包含在单个图表中)。但是,在Grafana中,这并不总是可能的,具体取决于您使用的数据源。例如,Grafana的Graphite数据源本身支持时移,但许多其他源不支持。

对于PostgreSQL数据源,可以进行时移,而创建时移图的最佳方法是使用PostgreSQL的LATERAL JOIN函数。

使用该LATERAL JOIN函数,我们可以创建时移图以进行监视和历史分析,如下所示:

image.png
该时移图显示了今天(绿色)和过去3天的出租车车程。

image.png
时移图显示给定日期(黄线)和前一周(绿线)的出租车车程

自己尝试:Grafana和示例查询中的实现

为了帮助您掌握在将样本数据集应用于自己的项目之前在其上创建时移图的习惯,我整理了这份方便的分步指南。

情境

我们将使用监视IoT设备的用例,特别是配备了位置检测传感器的出租车。我们的数据集来自2016年1月的纽约出租车和豪华轿车委员会(NYC TLC)。

先决条件

  • 运行PostgreSQL 11+的TimescaleDB实例(Timescale Cloud或自托管)
  • Grafana实例(云或自托管)
  • 要连接到Grafana的TimescaleDB实例(请参阅我们的Grafana设置教程),要将出租车数据集加载到TimescaleDB中,请完成本教程中的Mission 1,它将带您下载.CSV文件并将数据插入数据库。

示例1:建立3天时移

假设我们要回答:“ 今天的出租车活动与前三天的活动相比如何?

这是完整的查询,带有注释,显示了如何使用PostgreSQL LATERAL JOIN函数创建一个图表,该图表显示当前的乘车次数以及前三天的时移乘车次数。

-- What to name the series
SELECT time, ride_count, CASE WHEN step = 0 THEN 'today' ELSE (-interval)::text END AS metric
FROM
-- sub-query to generate the intervals
    ( SELECT step, (step||'day')::interval AS interval FROM generate_series(0,3) g(step)) g_offsets
    JOIN LATERAL (
-- subquery to select the rides 
    SELECT
-- adding set interval to time values
      time_bucket('15m',pickup_datetime + interval)::timestamptz AS time, count(*) AS ride_count FROM rides
-- subtract value of interval from time to plot
-- today = 0, 1 day ago = 1, etc
    WHERE pickup_datetime BETWEEN $__timeFrom()::timestamptz - interval AND $__timeTo()::timestamptz - interval
    GROUP BY 1
    ORDER BY 1
    ) l ON true

查询以15分钟为间隔的乘车图,前3天有时移

这将产生以下图形:
image.png
该图显示了2016年1月乘坐的出租车,时移将今天的出租车与前三天的出租车进行比较。今天的游乐设施以绿色显示,红色为-1天,蓝色为-2天,黄色为-3天。

如果放大到两天的时间段(通过使用时间选择器进行选择或在图表中突出显示),我们可以看到时移如何允许我们比较乘车活动,只需将鼠标悬停在任意给定时间间隔上的图表上即可:

image.png
该图显示了2016年1月12日和2016年1月13日乘坐的出租车,时移将今天的出租车与前三天进行比较,放大到任意2天的时间段。今天的游乐设施以绿色显示,红色为-1天,蓝色为-2天,黄色为-3天。

查询的工作方式:

在此查询中,LATERAL JOIN函数类似于“ for each”循环,使子查询的结果可用于随后的子查询的LATERAL JOIN每个结果。

在这种情况下,之前的查询会LATERAL JOIN生成我们要比较乘车活动的时间间隔。由于我们要比较任一给定日期与过去3天的行驶行为,因此我们生成了0、1、2和3天的间隔:

-- sub-query to generate the intervals
( SELECT step, (step||'day')::interval AS interval 
FROM generate_series(0,3) g(step)) g_offsets

查询以生成间隔以比较乘车活动

在后面的查询中LATERAL JOIN,我们在15分钟的时间段中绘制了我们感兴趣的时段内的游乐设施数量。注意我们如何使用interval上一个子查询中的值:通过interval在time_bucket函数和WHERE子句中添加和减去in 来过滤选定游乐设施的时间范围,我们能够获取当前时间间隔和时移间隔的正确值:

-- subquery to select the rides 
(SELECT
-- adding set interval to time values  time_bucket('15m',pickup_datetime + interval)::timestamptz AS time, count(*) AS ride_count 
FROM rides
-- subtract value of interval from time to plot
-- today = 0, 1 day ago = 1, etc
WHERE pickup_datetime BETWEEN $__timeFrom()::timestamptz - interval 
AND $__timeTo()::timestamptz - interval
GROUP BY 1
ORDER BY 1)

查询我们绘制当前时段和时移时段的15分钟时段内的游乐次数

有关更多信息LATERAL JOIN,请参见Heap的人员和PostgreSQL官方文档中的此有用教程。

视觉专业提示:添加系列替代

为了更容易地区分任何一天的游乐设施和前三天的游乐设施,我们可以应用一系列的覆盖来修改时移线的外观:

image.png
系列优先参数可区分实线和时移线

使用上面的参数,我们对时间平移的序列应用序列替代,以使它们的线宽小于实际的线宽,从而使我们能够更轻松地区分它们。然后,我们可以在“显示”设置下查看非时移的线-在下面的图像中,线宽设置为5,线设置为2:

image.png
应用了视觉处理的当前游乐设施和前3天时移的最终图形

示例2:建立1周时移

接下来,我们要回答:“本周的活动与上周相比如何?

在此示例中,我们创建了一个图表以显示当前的乘车次数,并创建了一条时移线以绘制前一周的乘车图。

大部分查询与示例1中的查询相同。唯一的区别是(1)间隔定义从更改day为week和(2)我们生成的系列只有两个值,即0和1,因为我们只想与前一周进行比较(对比前一周的3天时间段)例。)

SELECT time, ride_count, 
	CASE WHEN step = 0 THEN 'today' ELSE (-interval)::text END AS metric
FROM
    ( SELECT step, (step||'week')::interval AS interval FROM generate_series(0,1) g(step)) g_offsets
JOIN LATERAL (
    SELECT
      time_bucket('15m',pickup_datetime + interval)::timestamptz AS time, count(*) AS ride_count FROM rides
    WHERE
      pickup_datetime BETWEEN $__timeFrom()::timestamptz - interval AND $__timeTo()::timestamptz - interval
    GROUP BY 1
    ORDER BY 1
) l ON true

查询以绘制当前游乐设施和1周时移游乐设施

这将产生以下图形:

image.png
该图显示了2016年1月乘坐的出租车,时移以将今天的乘车时间与上一周进行比较,放大到任意5天的时间段。一天中的游乐设施以绿色显示,前一周最后一天的游乐设施以黄色显示。

视觉专业提示:添加系列替代

为了更容易地区分任何一天的游乐设施和前一周的游乐设施,我们可以应用一系列改写来更改时移线的外观:

image.png
该图显示了当前游乐设施和1周时移游乐设施,并应用了系列替代功能,以直观地区分出时差和非时移行

为此,我们将行区域设置为0(在“显示设置”下),然后将序列替代应用于时移序列。

在系列替代设置中,我们:

  • 将线条填充设置为2,给我们阴影效果
  • 将线宽设置为0,使非时移图形成为唯一带有实线的序列,从而使其更加可区分。

image.png
系列优先设置使时移的线更容易区分

下一步

在本教程中,我们介绍了时移是什么,它如何工作以及如何使用PostgreSQL LATERAL JOIN,TimescaleDB和Grafana可视化时移,从而轻松地比较两个(或多个!)时间段内的数据。

⏰要将查询修改为时移任意分钟,数小时,数天,数月或数年的时间,更改参数generate_series和interval定义(虽然现在最常见的是将指标与以前的期间进行比较,但是您可以使用时移来比较任何两个时间段)。

时移快乐!

文章来源:https://blog.timescale.com/blog/grafana-postgres-timeshift/?utm_source=db-weekly-sponsor&utm_medium=email&utm_campaign=db-weekly-sponsor-aug-2020&utm_content=grafana-timeshift-blog

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论