时序数据库
时序数据库(Time Series Database)是一种专门用于存储和处理时间序列数据的数据库系统。时间序列数据是按时间顺序排列的数据集,通常包含时间戳和与之相关的数值或事件。
应用场景较广泛,适用与对需要对大量数据进行存储和分析,以实现实时监控、预测和决策支持:
- 物联网 (IoT) :时序数据库用于存储和分析传感器数据、设备状态数据等,便于进行实时监控、预测和故障诊断。
- 能源管理:时序数据库用于存储和分析能源管理系统中的数据,如电力负荷数据、能源产量等,有助于能源监测和优化。
- 金融交易:时序数据库用于存储金融交易数据,如股票价格、汇率等,有助于实时交易决策、风险管理和投资分析。
- 工业自动化:时序数据库用于存储和分析工业自动化系统中的数据,如生产线数据、设备运行状态等,有助于实时监控和优化。
- 环境监测:时序数据库用于存储和分析环境监测系统中的数据,如气象数据、水质数据等,有助于环境保护和治理。
国内目前主流时序数据库有三种:InfluxDB、TDEngine、Apache IoTDB。时序数据库比较
IotDB数据库
介绍
IoTDB 是针对时间序列数据收集、存储与分析一体化的数据管理引擎,即数据收集-数据写入-数据存储-数据查询-数据可视化-数据分析。
具有体量轻、性能高、易使用的特点,完美对接 Hadoop 与 Spark 生态,适用于工业物联网应用中海量时间序列数据高速写入和复杂分析查询的需求。
官网:https://iotdb.apache.org/zh/UserGuide/latest/QuickStart/QuickStart.html
快速了解:Apache/IoTDB
特点:
- IotDB部署方式支持单机模式和集群模式两种,集群模式下支持秒级自动故障转移,尽可能减少切换的数据丢失和单点故障问题。
- 读写性能比较好,也支持读写分离
- 存储方面支持PB级数量的存储和处理能力,支持20倍以上的无损压缩比和100倍压缩比。
- 支持类SQL标准
数据模型概念:
以从 root节点到叶子节点的路径来命名一个时间序列,层次间以"."连接。例如,下图最左侧路径对应的时间序列名称为ROOT.ln.wf01.wt01.status。类似于Linux文件系统、ZK的DataTree模型。

基础概念:
|--------|-----------------------------|
| 概念 | 解释 |
| 物理量 | 测量信息,可理解于实体的字段(属性) |
| 实体 | 具体的物理设备,每个物理量归属到实体上 |
| 数据库 | 任意前缀路径可作为数据库,每层数据库可存多个实体的数据 |
| 数据点 | 时间戳与值的键值对 |
| 时间序列 | 数据点的所有记录,一个实体的一个物理量对应一个时间序列 |
数据类型与编码方式:
iotdb的数据类型,压缩方式,编码方式_gorilla 编码-CSDN博客
Integer.MAX_VALUE和Integer.MIN_VALUE是什么?-CSDN博客
IoTDB数据类型与编码方式_iotdb text类型-CSDN博客
可视化管理工具:Timecho WorkBench
https://www.timecho.com/archives/timecho-workbench-v1.0.1.1-fa-bu
本地化管理iotdb数据库
启动jar包:java -jar workbench.jar &
本地通过 http://127.0.0.1:9090/ 可以管理数据库
快速上手:sql语句
实践应用(不推荐JDBC):
1.原生jdk建立IotSession管理:
SpringBoot整合IotDB(利用Mybatis、Session两种方式)_gradle引入iotdb session-CSDN博客
SpringBoot整合IoTDB_iotdb springboot开发代码-CSDN博客
java
//Mavean添加依赖
<dependency>
<groupId>org.apache.iotdb</groupId>
<artifactId>iotdb-session</artifactId>
<version>0.10.1</version>
</dependency>
//配置文件
spring:
iotdb:
ip: 192.111.110.10
port: 6667
user: root
password: root
fetchSize: 10000
//建立bean对象
@Configuration
public class IotConfigProperties {
@Value("${spring.iotdb.ip}")
private String ip;
@Value("${spring.iotdb.port}")
private int port;
@Value("${spring.iotdb.user}")
private String user;
@Value("${spring.iotdb.password}")
private String password;
@Value("${spring.iotdb.fetchSize}")
private int fetchSize;
@Bean
public Session iotSession(){
return new Session(ip,port,user,password,fetchSize);
}
// @Bean
// public Session iotSession(){
// Session s = Session.Builder().host(host).port(port).user(user).password(password).fetchSize(fetchSize).build();
// s.open(false)
// return s
// }
}
//service层引用
@Resource
private Session iotSession;
https://blog.51cto.com/u_16213357/7243082
2.sessionpool管理
作用:
SessionPool是会话集的包装器。使用SessionPool,用户不需要考虑如何重用会话连接。即使会话已断开连接,会话池也可以识别它,并删除断开的会话连接并创建新的会话连接。如果没有可用的连接并且池达到其最大大小,则所有方法都将挂起,直到有可用的连接为止。如果用户等待会话的时间超过60秒,则会打印警告日志。
关键流程:
- **检测连接状态:**sessionPool会定期或者再需要时检测连接的状态,以确定连接是否处于活动状态。
- **重连机制:**如果连接断开或者不可用,通常会尝试重新建立连接。(默认机制:是会尝试3次,每次间隔1s;若该连接还是断开或者不可用,会被标记为不可用,并被sessionPool从连接池中删除)
- **连接恢复:**sessionPool成功建立连接,连接数会被添加回线程池,并标记为可用状态。
- **连接失败处理:**如果重连尝试失败或者达到最大重连次数,sessionPool会按策略进行处理。(默认会从连接池中删除这些不可用的连接)
解释:
当通过sessionPool进行连接时,如果有可用的连接,就直接复用;如果没有会创建新的连接(连接数不超过maxSize)。由于iotdb连接的建立断开等操作都封装在了每一个查询或者插入操作的getSession()方法;所以当iotdb由于内存或者网络等问题发生异常,导致数据库连接断开时,此时若继续进行查询存储等操作,sessionPool才会报Fail to reconnect to server错误。

注:new SessionPool()只是生成了一个对象,该对象存放了线程池的参数信息,这些参数包含自定义和默认两部分。此时并没有和iotdb建立连接。

SessionConfig存放了一些默认参数。

示例代码
java
import org.apache.iotdb.session.pool.SessionPool
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import javax.annotation.Resource
@Configuration
@ConfigurationProperties(prefix = "spring.iot-db")
public class IotConfigProperties {
private String ip;
private int port;
private String user;
private String password;
private int fetchSize;
}
@Configuration
public class IotSessionConfig {
@Resource
private IotConfigProperties iotConfigProperties;
@Bean("iotSessionPool")
public SessionPool getSessionPool(){
return new SessionPool(
iotDBProperties.host,
iotDBProperties.port,
iotDBProperties.username,
iotDBProperties.password,
iotDBProperties.maxsize,
)
}
}
查询数据处理方式
java
/**
* 查询返回RowRecord方式
* @throws Exception
*/
public static void query()throws Exception{
Session session = new Session("127.0.0.1",6667,"root","root");
session.open();
SessionDataSet dataSet = session.executeQueryStatement("select * from root.sestest.wf01.wt01");
List<String> list = dataSet.getColumnNames();
for (String s : list) {
System.out.printf("%-35s",s );
}
System.out.println();
dataSet.setFetchSize(1024);//IOTDB自身分页,只会建立一次连接,然后按fetchsize大小分批次返回数据
while (dataSet.hasNext()){
RowRecord record = dataSet.next();
// if (!rowRecord.hasNullField()) {//去掉有一行记录中有null值的记录
System.out.printf("%-35s",record.getTimestamp());
for (Field field : record.getFields()) {
System.out.printf("%-35s",field.getIntV());
}
System.out.println();
// }
}
dataSet.closeOperationHandle();
session.close();
}
IoTDB在springboot2中的(二) 查询_springboot + iotdb 实现数据的查询-CSDN博客
特别地
1.设备对齐模式 align by device:想要在返回结果中,加上设备序列路径时可使用。该字段原生jdk中目前无接口支持,只能用sql查询。此时需要根据场景考虑sql注入的问题。
一些防止sql注入的建议
- 对输入的数据,进行输入验证和过滤。通过正则表达式进行过滤,不符合规则不通过。如物理量名称:
路径名称:支持中文 英文 数字 . _ 和*(不能放在路径开头)
时间:支持 数字 (方法改成仅支持时间戳)
时间间隔:支持 英文字母和数字
且都不支持空格字符
- sql拼接前,对特殊字符进行转义:
单引号 ' 被转义为两个单引号 ''
双引号 " 被转义为 \"
反斜杠 \ 被转义为 \\
空字符 \0 被转义为 \0
退格符 \b 被转义为 \b
换行符 \n 被转义为 \n
回车符 \r 被转义为 \r
制表符 \t 被转义为 \t
替换字符 \u001A 被转义为 \Z
- 手动构建查询语句,将用户输入的值通过字符串拼接的方式插入到查询语句:
String query = "SELECT * FROM devices WHERE name = '" + deviceName + "'";
2.分段分组函数:某个时间段,按区间分组,从各个分组中获取一个数据。
select FIRST_VALUE(temperature) as value from root.deviceManagement.M_10.SN1 group by ([2024-01-30 10:45:00, 2024-01-30 19:00:00), 15m) align by device;
3.官方不建议jdbc
jdbc和sessionPool查询效率差不多,但是以后全库查可能有风险