首页 > 数据库 >Tdengine的时序数据库简介、单机部署、操作语句及java应用

Tdengine的时序数据库简介、单机部署、操作语句及java应用

时间:2024-06-11 13:03:25浏览次数:12  
标签:beijing java electric Tdengine 08 时序 2024 06 data

Tdengine的时序数据库简介、单机部署、操作语句及java应用

     本文介绍了Tdengine的功能特点、应用场景、超级表和子表等概念,讲述了Tdengine2.6.0.34的单机部署,并介绍了taos数据库的常见使用方法及特色窗口查询方法,最后介绍了在java中的应用。

一、tdengine简要介绍及应用场景

1、简要介绍

TDengine是涛思数据专为物联网、车联网、工业互联网、IT运维等设计和优化的大数据平台,是一款优秀的时序数据库。

2、应用场景

  • 公共安全:上网记录、通话记录、个体追踪、区间筛选
  • 电力行业:智能电表、电网、发电设备的集中监测
  • 通讯行业:话费详单、用户行为、基站/通讯设备监测
  • 金融行业:交易记录、存取记录、ATM、POS 机监测
  • 出行工具:火车/汽车/出租/飞机/自行车的实时监测
  • 交通行业:实时路况,路口流量监测,卡口数据;
  • 石油石化:油井、运输管线、运输车队的实时监测
  • 互联网: 服务器/应用监测、用户访问日志、广告点击日志
  • 物流行业:车辆、集装箱的追踪监测
  • 环境监测:天气、空气、水文、地质环境等监测;
  • 物联网: 电梯、锅炉、机械、水表、气表等各种联网设备
  • 军工行业:各种军事装备的数据采集、存储
  • 制造业: 生产过程管控,流程数据、供应链数据采集与分析

  如果采用传统的方式,将多个设备的数据写入一张表,由于网络延时不可控,不同设备的数据到达服务器的时序是无法保证的,写入操作是要有锁保护的,而且一个设备的数据是难以保证连续存储在一起的。采用一个数据采集点一张表的方式,能最大程度的保证单个数据采集点的插入和查询的性能是最优的。

二、tdengine功能特点

1、相比mysql可以查询快10倍以上;

2、提供缓存、数据订阅、流式计算等功能;

3、提供了独有的按时间自动划分窗口并执行查询的能力;

4、自动按照时间戳建立索引,但对采集的物理量不建任何索引。数据用列式存储方式保存。

三、tdengine技术概念(超级表和子表)

        1、引入超级表和子表概念,并提供窗口查询。taos数据库常用于具有时序的大量数据存储,能够快速查询并定时清除历史数据。诸如能源系统的电表、水表、气表等,通过mqtt采集后的实时数据,存储在tdengine中,对于每一类的采集设备或者采集数据,有着相似的数据结构,便建立“超级表”定义表结构,设置tags标签用于建立,超级表下的子表,通常每一个上报数据的设备建立一个子表。

        超级表有效用于聚合查询等数据分析,子表用于单设备节点的实时数据分析,超级表和子表的查询有连接的地方。

       2、 超级表是指某一特定类型的数据采集点的集合。同一类型的数据采集点,其表的结构是完全一样的,但每个表(数据采集点)的静态属性(标签)是不一样的。

        能源管理系统中数据量最大的就是各个智能抄表、传感器上报的数据。这些智能抄表的上报数据要进行长期记录,并定期查询、统计生成报表;在系统中,也需要在用户点击查看具体设备时,显示出该设备的实时读数以及历史变化曲线等。

        随着公司业务的不断扩大,所有客户的数据我们还需要一个总的平台来监测存储,传统的关系型数据库已经不足以支撑业务量,因此针对抄表数据时序结构化的特点选择合适的数据库变得非常重要。 

        子表用来代表一个具体的数据采集点,超级表用来代表一组相同类型的数据采集点集合。

四、单机版tdengine部署

1、下载TDengine离线rpm安装包

​
wget https://www.taosdata.com/assets-download/TDengine-server-2.6.0.34-Linux-x64.rpm

​

2、安装离线包

sudo yum install TDengine-server-2.6.0.34-Linux-x64.rpm –y

3、启动tdengine

sudo systemctl start taosd

systemctl start taosadapter

taos

alter user root pass 'admin123';

五、tdengine创建

1、创建数据库

#命令行执行,登陆taos数据库

taos

# 创建数据库ems

create database if not exists ems;

# 查看所有的数据库

show databases;

# 切换到数据库ems

use ems;

2、超级表和子表的结构与表名设计

超级表为某一类的数据结构,相当于表结构声明;子表为单节点的数据表,继承超级表的表结构,tag标签用于区分该类设备/数据的单节点。在java应用中,为便于查询,常将部分tag标签用于组建子表名。

    如下设计为电表的表结构,electric_meter_ui为超级表,通过定义标签location和sn创建子表,并将tag标签用于子表的命名。

超级表:electric_meter_ui

ts

Ua

Ub

Uc

typestatues

子表:electric_meter_ui_${location}${sn}

ts

Ua

Ub

Uc

typestatues

location

sn

(tag)

(tag)

3、超级表创建和结构修改

(1)超级表创建

# 创建超级表

CREATE STABLE `electric_data` (`ts`  TIMESTAMP,  `Ua` FLOAT , `Ub` FLOAT , `Uc`  FLOAT ) TAGS ( `location` NCHAR(100), `sn` NCHAR(100));

# 查看超级表

show stables;

# 查看超级表结构

DESCRIBE electric_data;

2)超级表结构修改-列删除
ALTER TABLE electric_data DROP COLUMN typestatues;
(3)超级表结构修改-列增加
ALTER TABLE electric_data ADD COLUMN typestatues INT;
(4)超级表结构修改-列修改
ALTER TABLE electric_data MODIFY COLUMN typestatues INT;

4、子表创建和数据新增

(1)子表创建

# 创建子表

create table electric_data_beijing_SN001 using electric_data tags("beijing",'SN001');

create table electric_data_beijing_SN002 using electric_data tags("beijing",'SN002');

create table electric_data_jinan_SN002 using electric_data tags("jinan",'SN002');

create table electric_data_shenzhen_SN005 using electric_data tags("shenzhen",'SN005');

# 查看子表结构

DESCRIBE electric_data_shenzhen_SN005;
(2)新增数据
taos> INSERT INTO electric_data_beijing_SN001 VALUES ('2024-06-08 00:05:12.272', 10.2, 200, 1);

Query OK, 1 row(s) affected (0.000859s)



taos> INSERT INTO electric_data_beijing_SN001 VALUES ('2024-06-08 01:05:12.272', 20.2, 210, 2);

Query OK, 1 row(s) affected (0.000272s)



taos> INSERT INTO electric_data_beijing_SN001 VALUES ('2024-06-08 02:05:12.272', 10.2, 220, 3);

Query OK, 1 row(s) affected (0.000233s)



taos> INSERT INTO electric_data_beijing_SN001 VALUES ('2024-06-08 03:05:12.272', 20.2, 200, 2);

Query OK, 1 row(s) affected (0.000385s)



taos> INSERT INTO electric_data_jinan_SN002 VALUES ('2024-06-08 12:04:12.272', 10.2, 200, 1);

Query OK, 1 row(s) affected (0.000696s)



taos> INSERT INTO electric_data_jinan_SN002 VALUES ('2024-06-08 13:05:12.272', 20.2, 210, 2);

Query OK, 1 row(s) affected (0.000346s)



taos> INSERT INTO electric_data_jinan_SN002 VALUES ('2024-06-08 14:05:12.272', 10.2, 220, 3);

Query OK, 1 row(s) affected (0.000305s)



taos> INSERT INTO electric_data_jinan_SN002 VALUES ('2024-06-08 15:05:12.272', 20.2, 200, 2);

Query OK, 1 row(s) affected (0.000299s)



taos> INSERT INTO electric_data_shenzhen_SN005 VALUES ('2024-06-08 15:09:12.272', 20.2, 200, 2);

Query OK, 1 row(s) affected (0.000327s)

taos> create table electric_data_beijing_SN002 using electric_data tags("beijing",'SN002');

Query OK, 0 row(s) affected (0.004323s)



taos> INSERT INTO electric_data_shenzhen_SN005 VALUES ('2024-06-08 15:09:12.272', 20.2, 200, 2);

Query OK, 1 row(s) affected (0.000352s)

(3)子表删除
drop table electric_data_beijing_SN001;

六、查询操作

主要示例数据:

INSERT INTO electric_data_beijing_SN001 VALUES ('2024-06-08 00:05:12.272', 10.2, 200, 1,1);

INSERT INTO electric_data_beijing_SN001 VALUES ('2024-06-08 01:05:12.272', 20.2, 210, 2,1);

INSERT INTO electric_data_beijing_SN001 VALUES ('2024-06-08 02:05:12.272', 10.2, 220, 3,1);

INSERT INTO electric_data_beijing_SN001 VALUES ('2024-06-08 03:05:12.272', 20.2, 200, 2,0);

INSERT INTO electric_data_beijing_SN001 VALUES ('2024-06-08 03:31:12.272', 20.2, 210, 2,0);

INSERT INTO electric_data_beijing_SN001 VALUES ('2024-06-08 05:05:12.272', 10.2, 200, 3,1);

INSERT INTO electric_data_beijing_SN001 VALUES ('2024-06-08 05:55:12.272', 10.2, 220, 3,1);

INSERT INTO electric_data_beijing_SN001 VALUES ('2024-06-08 06:55:12.272', 10.2, 210, 3,0);

 1、过滤查询

select count(*) from  `ems`.`electric_data` where `location` = 'beijing' ;

超级表的筛选条件可以是静态字段或者tag, 当筛选条件为所有tag时,等同于查询对应的子表,如下两个查询语句有相同结果:

select count(*) from  `ems`.`electric_data` where `location` = 'beijing' and `sn` = '001';

select COUNT(*) from  electric_data_beijing_SN001;

2、聚合查询

直接对超级表聚合查询<==>子表数据聚合查询

SELECT AVG(`Ua`), `location` FROM `ems`.`electric_data` GROUP BY `location`;

3、时间窗口查询(interval)

时间窗口通过对数据按时间顺序划分切割,实现数据的降采样,在时间窗口内的数据可以avg/max/min等聚合运算或时长计算,并提供了滑动窗口sliding以及自动填充方案FILL。

(1)interval等时间间隔窗口

如下是等时间间隔窗口示意图,未声明滑动窗口,则滑动窗口sliding=interval,时间窗口数据无重叠:

(2)sliding 滑动窗口

如下是等时间间隔窗口示意图,声明滑动窗口,则滑动窗口sliding<interval,时间窗口数据有重叠[t0s-t0e]和[t1s-t1e]:

(3)fill填充

FILL 语句指定某一窗口区间数据缺失的情况下的填充模式。填充模式包括以下几种:

不进行填充:NONE(默认填充模式)。

VALUE 填充:固定值填充,此时需要指定填充的数值。例如:FILL(VALUE, 1.23)。

PREV 填充:使用前一个非 NULL 值填充数据。例如:FILL(PREV)。

NULL 填充:使用 NULL 填充数据。例如:FILL(NULL)。

LINEAR 填充:根据前后距离最近的非 NULL 值做线性插值填充。例如:FILL(LINEAR)。

NEXT 填充:使用下一个非 NULL 值填充数据。例如:FILL(NEXT)。

(4)示例1(无滑动窗口)

# 从2024-06-08 00:00:00.000开始,每间隔1h的Ub平均值,如果区间的1h没数据,使用前一个非 NULL 值填充。

#查询结果有24条

SELECT avg(`Ub`) as Ub FROM electric_data_beijing_SN001 where  `ts` > '2024-06-08 00:00:00.000' and `ts` < '2024-06-09 00:00:00.000' interval(1h)

(5)示例2(有滑动窗口)

# 从2024-06-08 00:00:00.000开始,每间隔30min, 时长区间未1h的Ub平均值,如果区间的1h没数据,使用前一个非 NULL 值填充。

#查询结果有49条

SELECT avg(`Ub`) as Ub FROM electric_data_beijing_SN001 where  `ts` > '2024-06-08 00:00:00.000' and `ts` < '2024-06-09 00:00:00.000' interval(1h) sliding(30m) FILL(PREV);

4、状态窗口查询(state_window)

状态窗口让用户可以按照某个整型/字符串型的采集量(一般是表征状态的值,如设备工作模式等)的值来划分窗口,将该状态值连续不变的记录划入同一个窗口。然后对每个窗口内的采集值进行avg/max/min等统计聚合、或计算状态持续时间等。

(1)示例1 state_window

# typestatues连续不变的总共有4段,划分四个窗口,对窗口内的数据计算记录条数和持续时长。

select first(`ts`) as ts, `typestatues` as status,count(*) as record_count,spread(`ts`)/1000 as "duration(s)" from electric_data_beijing_SN001 where  `ts` > '2024-06-08 00:00:00.000' and `ts` <

 '2024-06-09 00:00:00.000' state_window(`typestatues`);

5、会话窗口查询(session)

会话窗口让用户可以按照上报记录的时间连续性来划分窗口,即相邻两条记录时间间隔不超过某一阈值,则划归同一窗口;超过该阈值,则老窗口结束,新窗口开始;然后对每个窗口进行诸如持续时间等统计,或对窗口内的原始采集数据进行各种聚合计算,可以是 avg/max/min/count 或其他用户自定义函数。

用于物联网中,上设备连续上报数据时表名在线,如果间隔时间过长,表明不在线,我们对数据基于间隔时间最大阈值进行划分,更有效的分析数据。

(1)示例1 session

# 上报数据间隔时间超过1h的,作为窗口切分的边缘;

# 结果分为划分为两个窗口,对窗口内的数据计算记录条数和持续时长。

select last(`ts`) as session_endtime, spread(ts)/1000 as 'duration(s)',count(*) as record_count from `ems`.electric_data_beijing_SN001 session(ts,1h);


七、java下的tdengine操作

1、通过HttpUtils网址调用

// 拼接子表表名
 String sqls = "select last_row(*) from electric_data_".concat(location.toString()).concat("_").concat(sn);
// 查询
JSONObject Json = JSONObject.parseObject(httpUtil.postTDengine(sqls));
  

Urs = jdbc:TAOS-RS://47.95.215.167:6041/ems

   public String postTDengine(String sqls) {

        CloseableHttpResponse response = null;

        BufferedReader in = null;

        String result = "";

        try {

            HttpPost httpPost = new HttpPost(url);

            RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30000).setConnectionRequestTimeout(30000).setSocketTimeout(30000).build();

            httpPost.setConfig(requestConfig);

            httpPost.setConfig(requestConfig);

            httpPost.addHeader("Content-type", "text/plain; charset=utf-8");

            httpPost.addHeader("Authorization", "Basic " + authorizationToken);

            httpPost.setHeader("Accept", "*/*");

            httpPost.setEntity(new StringEntity(sqls, Charset.forName("UTF-8")));

            response = httpClient.execute(httpPost);

            in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));

            StringBuffer sb = new StringBuffer();

            String line = "";

            String NL = System.getProperty("line.separator");

            while ((line = in.readLine()) != null) {

                sb.append(line + NL);

            }

            in.close();

            result = sb.toString();

        } catch (IOException e) {

            e.printStackTrace();

        } finally {

            try {

                if (null != response) {

                    response.close();

                }

            } catch (IOException e) {

                e.printStackTrace();

            }

        }

        return result;

}

2、通过mapper接口层调用

<dependency>
    <groupId>com.taosdata.jdbc</groupId>
    <artifactId>taos-jdbcdriver</artifactId>
    <version>3.0.4</version>
</dependency>

username: root
password: taosdata
url: jdbc:TAOS-RS://47.95.215.167:6041/ems
driver-class-name: com.taosdata.jdbc.rs.RestfulDriver

主要参考网站

按窗口切分聚合 | TDengine 文档 | 涛思数据

https://www.sohu.com/a/602180065_121276745

标签:beijing,java,electric,Tdengine,08,时序,2024,06,data
From: https://blog.csdn.net/xingyuemengjin/article/details/139585150

相关文章

  • AAAjavaweb复习
     packagecom.xxxx.servlet;importjakarta.servlet.*;importjakarta.servlet.http.*;importjakarta.servlet.annotation.*;importjava.io.IOException;/*创建Servlet类*/@WebServlet(name="TestServlet01",value="/TestServlet01")publi......
  • AAAjavaweb复习-个人代码复习
    1:packagecom.xxxx.servlet;importjakarta.servlet.;importjakarta.servlet.http.;importjakarta.servlet.annotation.*;importjava.io.IOException;/创建Servlet类/@WebServlet(name="TestServlet01",value="/TestServlet01")publicclas......
  • Java (MyBatis-Plus 项目)
    前沿MyBatis-Plus在使用这个时候的它通过提供简洁、强大的API和注解支持,简化了常见的数据库操作。以下是关于MyBatis-Plus中注解的解释和示例,理解和使用1.实体类注解@TableName:用于指定数据库表的名称。@TableId:用于指定主键字段。@TableField:用于指定非主键字段......
  • Java实现定时任务的几种方式 ---------内附源码
      在我们日常项目开发过程中,经常用到定时任务,如果使用不当甚至会造成资源损毁,定时任务使用不当,会导致发出大量重复操作,可能会造成巨大的后果。  所以,系统的学习一下定时任务,是非常有必要的。这篇文章就带大家整体梳理学习一下Java领域中常见的几种定时任务实现。 ......
  • JavaScript基础用法(变量定义、输入输出、转义符、注释和编码规范)
    天行健,君子以自强不息;地势坤,君子以厚德载物。每个人都有惰性,但不断学习是好好生活的根本,共勉!文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。文章目录JavaScript基础用法1.变量1.1语法1.2示例代码1.3浏览器效果2.输入和输出2.1输出2.1.1输......
  • 回顾Java中的安全模型
    Java中的安全模型是一个多层次、综合性的框架,旨在确保Java应用程序的安全运行。该模型包括多个关键组件和机制,以下是对Java安全模型的详细解释:沙箱模型(Sandbox):Java应用程序运行在一个受限的环境中,即沙箱。沙箱限制了应用程序对系统资源的访问,从而防止了恶意代码对系统造成......
  • 描述常见的Java安全漏洞和防范措施
    常见的Java安全漏洞及其防范措施可以归纳如下:一、常见的Java安全漏洞跨站脚本攻击(XSS)漏洞描述:攻击者通过在网页中插入恶意脚本来获取用户的敏感信息或执行恶意操作。防范措施:输入验证和过滤:对用户输入的数据进行严格验证和过滤,剔除恶意脚本。输出转义:在将用户数据输出......
  • java 异常处理方法
    java异常处理方法privateStringassembleErrorMessage(Exceptione){JSONObjecterrorMessage=newJSONObject();Optional<StackTraceElement>stackTraceElement=Arrays.stream(e.getStackTrace()).findFirst();Stringcause=e.toString(......
  • JAVA版本号的问题 Java版本号与JDK版本
    分不清Java版本和JDK版本的对应关系。抄一篇记忆一下。Java版本叫法:Java6、Java8、Java11、Java13(当前最新版本Java17)等这一类“JavaX”的Java版本名称同时又会听到,看到JDK版本叫法:JDK1.6、JDK1.8等这种“JDK1.X”的JDK叫法。这里我们就需要追溯一下Java的发展历程......
  • Java整合FreeMarker导出Pdf文件
    引入依赖<!--Freemarkerwls--> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.30</version> </dependency> <dependency> <groupId>......