InfluxDB 聚合函数实用案例
文章大纲

InfluxDB 简介
InfluxDB是GO语言编写的分布式时间序列化数据库,非常适合对数据(跟随时间变化而变化的数据)的跟踪、监控和分析。在我们的项目中,主要是用来收集设备实时上传的值。从而分析该设备值的趋势图和各个设备的能耗占比等一系列功能。InfluxDB的功能很强大,文档也很详细。可美中不足的是,它的单机性能并不是很理想。因为InfluxDB存储的数据量本身是非常巨大的,在执行一些时间范围比较大的sql语句,耗时会很长,甚至直接崩溃。而开源的InfluxDB目前已经不再支持集群。若要通过搭建集群提升性能问题,可以考虑企业版。当然,我们写的程序也有很大的性能优化空间。
能耗趋势图分析
需求:统计指定设备、指定区域、指定分项或者指定能耗类型的能耗趋势图。如下图所示,纵坐标是能耗值,横坐标是时刻(每小时、每天、每周、每月)。

分析:获取某个区间时刻的值,可以用GROUP BY time 进行时间分组。再用聚合函数LAST或者SUM统计。但这个看似很简单的需求却暗藏杀机。SQL语句如下
SELECT LAST("currentValue"), * FROM "$TABLE_NAME"
WHERE time > '$startTime' AND time <= '$endTime' AND id = '$id'
GROUP BY time($timeSpan)
ORDER BY time DESC
第一:先要清楚,数据是通过什么规则保存到InfluxDB数据库
为了记录设备能耗的实时数据,我们会通过订阅MQTT通道,当值发生变化后存储到InfluxDB数据库中,或者在指定时间范围内没有变化也会上传。这样做的好处可以避免一些冗余数据,同时也埋下了一个坑。
例如:一台设备在InfluxDB数据库中最后一次记录的时间是15分钟前。但是sql语句是从5分钟前开始统计。这会导致该设备的其点值就是null。简单来说:设备的存储的值正好在分组统计的时间范围外。解决方法有很多:比如用FILL(previous)函数填充;比如使用time(time_interval,offset_interval)进行时间推移等。但是我比较推荐下面的方法:
先获取指定开始时间之前的最后值(lastValue),然后再根据返回值是否为null,来决定是否替换或者更新lastValue。伪代码如下。
## 获取该设备的最后记录值
val lastValue = "SELECT LAST("currentValue") FROM "$TABLE_NAME" WHERE time <= '$startTime'"
## 遍历查询结果,将currentValue为 null的值替换
"SELECT LAST("currentValue"), * FROM "$TABLE_NAME"
WHERE time > '$startTime' AND time <= '$endTime' AND id = '$id'
GROUP BY time($timeSpan)
ORDER BY time DESC".forEach {
lastValue = currentValue?: lastValue
result[time] = currentValue?: lastValue
}
你以为这样就结束了吗?还不够,返回的time格式化后,你会发现有8小时的时区问题。
第二:解决InfluxDB时区问题
InfluxDB 默认以UTC时间存储并返回时间戳,查询返回的时间戳对应的也是UTC时间。我们需要通过tz()子句指定时区名称,比如Asia/Shanghai。若InfluxDB安装在Windows环境上,可能还会出现 error parsing query: unable to find time zone 错误,解决方法是安装GO语言环境,文章也详细介绍过。
SELECT LAST("currentValue"), * FROM "$TABLE_NAME"
WHERE time > '$startTime' AND time <= '$endTime' AND id = '$id'
GROUP BY time($timeSpan)
ORDER BY time DESC tz('Asia/Shanghai')
实用tz() 子句后,返回的时间格式:"2019-11-18T13:50:00+08:00"。需要通过 "yyyy-MM-dd'T'HH:mm:ss" 将其格式化。
第三:GROUP BY time 自然月
group by time 支持秒、分钟、小时、天和周,却唯独不支持自然月。如果对数据的精准性要求不高,可以考虑使用30d实现。或者分12次统计。或者有更好的方法,请不吝赐教
InfluxDB 聚合函数实用案例的更多相关文章
- SQL语句汇总(三)——聚合函数、分组、子查询及组合查询
聚合函数: SQL中提供的聚合函数可以用来统计.求和.求最值等等. 分类: –COUNT:统计行数量 –SUM:获取单个列的合计值 –AVG:计算某个列的平均值 –MAX:计算列的最大值 –MIN:计 ...
- JAVA实用案例之文件导出(JasperReport踩坑实录)
写在最前面 想想来新公司也快五个月了,恍惚一瞬间. 翻了翻博客,因为太忙,也有将近五个多月没认真总结过了. 正好趁着今天老婆出门团建的机会,记录下最近这段时间遇到的大坑-JasperReport. 六 ...
- mysql之聚合函数、group by、having
sql中提供聚合函数可以用来统计,求和,求最值等 那么聚合函数有哪些呢? COUNT 统计行数量 SUM 求某一列的和 AVG 求某一列的平均值 MAX 求某 ...
- SQL语句汇总(三)——聚合函数、分组、子查询及组合查询
拖了一个星期,终于开始写第三篇了.走起! 聚合函数: SQL中提供的聚合函数可以用来统计.求和.求最值等等. 分类: –COUNT:统计行数量 –SUM:获取单个列的合计值 –AVG:计算某个列的平均 ...
- Hive学习之自己定义聚合函数
Hive支持用户自己定义聚合函数(UDAF),这样的类型的函数提供了更加强大的数据处理功能. Hive支持两种类型的UDAF:简单型和通用型.正如名称所暗示的,简单型UDAF的实现很easy,但因为使 ...
- influxDB聚合类函数
1)count()函数 返回一个(field)字段中的非空值的数量. SELECT COUNT(<field_key>) FROM <measurement_name> [WH ...
- hibernate学习系列-----(5)hibernate基本查询下篇:hibernate聚合函数、分组查询及命名查询
在上一篇中,大致学习了hibernate的基本查询:HQL基本查询,今天,继续昨天的步伐,继续学习hibernate的基本查询..... 1.hql聚合函数,先大致列一下hql的聚合函数有哪些吧: 在 ...
- redux 的简单实用案例
redux 的简单实用案例 整体思想与结构 创建一个Action 创建一个Reducer 创建Store 在App组件开始使用 整体思想与结构 文件目录如下: 构建 action,通过创建一个函数,然 ...
- 【软件实施面试】MySQL和Oracle联合查询以及聚合函数面试总结
软件实施面试系列文章第二弹,MySQL和Oracle联合查询以及聚合函数的面试总结.放眼望去全是MySQL,就不能来点Oracle吗?之前面过不少公司,也做过不少笔试题,现在已经很少做笔试题了.你肚子 ...
随机推荐
- MongoDB-系统时钟跳变引发的风波
目录 背景 一. 对 oplog 的影响 oplog 原理 二.主备倒换 小结 声明:本文同步发表于 MongoDB 中文社区,传送门: http://www.mongoing.com/archive ...
- 记录一次gdb debug经历
目录 问题描述 查看core文件 使用gdb查看core文件 总结 问题描述 今天在写代码时,运行时奔溃了.segment fault,而且是在程序退出main()函数后,才报的. 唯一的信息是:Se ...
- java中多线程 - 多线程中的基本方法
介绍一下线程中基本的方法使用 线程睡眠sleep() Thread.sleep(毫秒);我们可以通过sleep方法设置让线程睡眠.可以看到sleep是个静态方法 public static nativ ...
- The usage of Markdown---目录
更新时间:2019.09.14 当我们编辑的内容比较多时,通常要生成目录来进行页内跳转.除了之前提到过的页内跳转链接的方法,还有一种方法--目录树,能够自动生产目录,大大减少工作量. tip1: ...
- 解决tortoiseSvn 访问版本库的时候一直初始化,或者无响应的问题
现象 svn访问版本库时一直提示: please wait while the repository browser is initializing 没有反应,甚至3-4分钟才会出来,即便出来也会很卡 ...
- 设计模式(二十二)Command模式
一个类在进行工作时会调用自己或者是其他类的方法,虽然调用结果会反映在对象的状态中,但并不会留下工作的历史记录. 这时,如果我们有一个类,用来表示“请进行这项工作”的“命令”就会方便很多.每一项想做的工 ...
- SpringBoot与MybatisPlus3.X整合之动态表名 SQL 解析器(七)
pom.xml <dependencies> <dependency> <groupId>org.springframework.boot</groupId& ...
- MIT线性代数:19.行列式和代数余子式
- Java 实现一个 能够 进行简单的增删改查的 超市管理系统
1. 首先编写一个 Fruitltem 的商品类, 描述 商品的基本信息. 代码如下: 保证详细, 运行的起来, 有什么 问题也可以评论留言. /* * 自定义类, 描述商品信息 * * 商品的属性: ...
- 入门Android底层需要的一些技能
<Android的设计与实现> Android框架层<Linux系统编程手册> Linux系统编程<Android内核剖析> 编译框架和romC语言和Linux内核 ...