时序数据库的何、为何和如何
作者:社区 / 产品,用例
2022年9月1日
导航至
本文由Thamatam Vijay Kumar撰写。向下滚动以查看作者简介和照片。
现代网站充满了各种包含丰富图表、折线图、雷达图以及多图组合的仪表盘。世界对这样的图表和图形着迷,它们为千禧一代的Web应用程序提供了巨大的价值。有许多这样的图表库,它们提供交互式可视化并为用户提供数据洞察。
这些图表使用数据点绘制线条。这些图表库帮助我们分析从几分钟到数年的数百万个数据点,并通过工具提示、图例和聚合显示额外信息。
上述示例显示了图表显示数千个数据点的功能,帮助用户更智能化地分析引擎数据,了解引擎状况。
在这篇文章中,我们将介绍如何存储和查询时序数据,这是现代图表的主要数据源。
什么是时序数据?
时序数据是在特定时间间隔内收集的一系列数据点,使我们能够跟踪变量的变化。时序数据是按时间顺序或按时间序列对变量进行观察的序列。
由于时序数据中的数据点在不同的时间收集,因此观察结果之间存在潜在的关联性。这是时序数据与其他数据区别开来的一个特点。
时序数据可用于金融、医疗、制造、物联网、物理科学等领域。
例如包括
- 公司的股票价值
- 患者的各种健康参数(如血压、血糖、氧气)的健康监测值
- 各种汽车引擎传感器的值,如速度、扭矩、机油、冷却液
- 智能家庭监控器以调节温度和识别入侵者
以下是在时序格式中的汽车引擎传感器样本数据
如上所示,这些数据是关于汽车引擎在不同间隔的多个传感器的。这些数据帮助我们理解和分析引擎在不同时间范围内的状况。
何时使用时序数据
但何时我们可以使用时序数据,在什么用例中我们在时序数据库中存储数据?
如上所述,当你有一个连续的数据流来存储一段时间内或不同时间戳的值时,这些应用程序需要一种特殊的数据库。
常见的时间序列数据库应用场景包括
- 访问物联网数据(引擎、智能设备等)
- 监控网络服务、应用程序和基础设施
- 金融交易
- 自动驾驶汽车数据
- 自主交易算法
- 零售行业配送
此外,如果您预计需要存储任何数据流,并且需要连续的时间戳以及不同值,那么专门用于存储时间序列数据的数据库是最合适的。
您可能会问:为什么我们不能将数据存储在关系数据库而不是时间序列数据库中?(请参阅)
为什么使用时间序列数据库
随着时间的推移,时间戳数据的量持续增长,在常规数据库中存储连续数据流变得困难。
我们在观察物理世界中的每一个可用外部设备——汽车、医疗仪器、发电厂、电话、家用电器、人体等等。每一件事都有,或者将会有,一个传感器不断地发出时间序列数据。这需要一个能够处理如此大量数据的平台。
假设传感器每秒发送数据,您拥有10000台发动机,每台发动机有100个传感器值。这将导致数据库中存储超过80亿条记录。在一个月或一年的时间内,在传统数据库中存储如此大量的数据变得不可能,查询数据库以进行简单的查询(例如,获取一年的10个传感器的数据)也变得不可能。这就是为什么世界正在竞相采用时间序列数据库来存储和检索数据,用于时间序列用例和连续数据流。
时间序列数据库的两种替代品是 RDBMS 和 NoSQL。
关系数据库管理系统(RDBMS)可以用来存储和检索时间序列数据。由于RDBMS的灵活性,它们可以像TSDB一样存储相同的数据。一个关键的区别是,RDBMS没有针对时间序列数据进行优化,并且在数据量不断增长的情况下,插入和检索时间序列数据的速度会变慢,如上述示例中所述。
另一种类型的数据库,NoSQL,也常用于存储时间序列数据。由于NoSQL数据库在每条记录的数据格式方面更加灵活,它们适合从多个不同的来源捕获时间序列数据。然而,查询NoSQL数据库意味着仔细检查模式并针对它编写自定义查询。像不同类型的连接这样的复杂操作,在SQL方面的创新已经持续了几十年,在NoSQL领域可能会很慢,甚至有缺陷。
选择时间序列数据库
现在我们已经介绍了时间序列的什么是和为什么,让我们比较一下市场上的一些流行的时间序列数据库,以及如何存储和检索连续数据流的数据。
- InfluxDB
- Graphite
- OpenTSDB
- TimescaleDB
名称 | InfluxDB | Graphite | OpenTSDB | TimescaleDB |
描述 | 存储时间序列指标和事件的数据库管理系统 | 时间序列数据的日志记录和绘图工具 | 基于HBase的可扩展时间序列DBMS | 一个基于PostgreSQL,针对快速摄取和复杂查询优化的时间序列数据库 |
主要数据库模型 | 时间序列数据库管理系统 | 时间序列数据库管理系统 | 时间序列数据库管理系统 | 时间序列数据库管理系统 |
二级数据库模型 | 空间数据库管理系统 | 关系数据库管理系统 | ||
仅基于云 | 否 | 否 | 否 | 否 |
实现语言 | Go | Python | Java | C |
数据模式 | 无模式 | 是 | 无模式 | 是 |
类型 | 数值数据和字符串 | 仅数值数据 | 数值数据用于指标,字符串用于标签 | 数值、字符串、布尔值、数组、JSON blob、地理空间维度、货币、二进制数据,其他复杂数据类型 |
XML支持 | 否 | 否 | 否 | 是 |
二级索引 | 否 | 否 | 否 | 是 |
查询语言 | 类似SQL的查询语言 | 否 | 否 | 是 |
API和其他访问方法 | HTTP API JSON over UDP | HTTP API Sockets | HTTP API Telnet API | ADO.NET JDBC 本地C库 ODBC 大对象流式API |
支持的编程语言 | .Net, Clojure, Erlang, Go, Haskell, Java, JavaScript, JavaScript (Node.js), Lisp, Perl, PHP, Python, R, Ruby, Rust, Scala | JavaScript (Node.js), Python | Erlang, Go, Java, Python R, Ruby | .Net, C, C++, Delphi, Java, JavaScript, Perl, PHP, Python, R, Ruby, Scheme, Tcl |
服务器端脚本 | 否 | 否 | 否 | 用户定义函数、PL/pgSQL、PL/Tcl、PL/Perl、PL/Python、PL/Java、PL/PHP、PL/R、PL/Ruby、PL/Scheme、PL/Unix shell |
触发器 | 否 | 否 | 否 | 是 |
分区方法 | 分片 | 无 | 分片 | 是,跨时间和空间(哈希分区)属性 |
评估时间序列数据库以适应您的工作负载时,需要考虑几个因素
- 数据模型
- 查询语言
- 可靠性
- 性能
- 生态系统
- 运维管理和支持
通常,数据库评估基于性能目标。然而,性能只是整体评估的一部分。如果数据库在其数据模型、查询语言或您生产工作负载所需的可靠性方面存在不足,它将无法高效运行。上述表格比较了时间序列数据库在定性维度(数据模型、查询语言和可靠性)上的表现。
目前,在时间序列数据库不断增长的市场中,InfluxDB因其全面的时间序列数据库特性而脱颖而出。凭借良好的技术文档,安装、配置和使用InfluxDB非常简单。由于它是一种类似NoSQL的数据库,我们可以直接插入数据。
在做出决定之前,退后一步,研究您的堆栈、您团队的技能以及您现在和未来的需求。
如何存储和查询时间序列数据
让我们来看看如何在InfluxDB中存储和查询时间序列数据。
存储数据
下载和安装InfluxDB。(注意,撰写本文时,最新版本是InfluxDB 2.2)。
一旦InfluxDB安装并设置好用户权限,我们就可以写入和查询数据。
在写入InfluxDB之前,了解一些关键术语非常重要
-
测量:InfluxDB数据结构的一部分,用于描述存储在相关字段中的数据
-
标签:严格来说,标签是可选的,但大多数序列都包含标签以区分数据源,并使查询既简单又高效。标签键和标签值都是字符串。
-
字段(必需):字段键是必需的,始终是字符串;默认情况下,字段值是浮点数。
-
时间戳:在行尾提供,以纳秒为单位表示自1970年1月1日UTC以来的Unix时间 - 是可选的。如果您未指定时间戳,InfluxDB将使用服务器的本地纳秒Unix纪元时间戳。InfluxDB的时间默认为UTC格式。
如果您是时间序列数据库的新手,这些术语可能有点难以理解,因此这里有一个解释
InfluxDB的测量值类似于SQL数据库表。
InfluxDB的标签类似于SQL数据库中的索引列。
InfluxDB的字段类似于SQL数据库中的非索引列。
InfluxDB的点类似于SQL行。
InfluxDB提供了几种机制来写入和查询数据。
-
Telegraf插件
-
InfluxDB API
-
Influx命令行
在这里,我们使用API机制,通过提供的写入端点来写入和存储数据
/write HTTP端点
POST https://127.0.0.1:8086/write
我们可以使用上述API将数据写入InfluxDB。写入数据的语法如下:‘测量值, 标签键 = ’标签值’, 字段键 = ’字段值’, 纪元时间戳‘。
$ curl -i -XPOST "https://127.0.0.1:8086/write?db=mydb" --data-binary 'enginespeed,serialnumber=10001 value=129 1463689152000000000
enginespeed,serialnumber=10001 value=84 1463689152000000000
enginespeed,serialnumber=10001 value=79 1463689152000000000
torque,serialnumber=10001 value=11 1463689152000000000
torque,serialnumber=10001 value=23 1463689152000000000
torque,serialnumber=10001 value=32 1463689152000000000
power,serialnumber=10001 value=1200 1463689152000000000
power,serialnumber=10001 value=1100 1463689152000000000
power,serialnumber=10001 value=1000 1463689152000000000
HTTP/1.1 204 No Content
Content-Type: application/json
Request-Id: [...]
X-Influxdb-Version: 1.4.x
Date: Wed, 08 Nov 2017 18:04:02 GMT
此写入将数据插入多个测量值(发动机速度、扭矩、功率)中。
在这里,我们正在保存一系列纪元时间戳与汽车发动机值相关的数据。
这样,我们可以将连续数据流存储到InfluxDB中,以供进一步查询。
同样,也可以使用CLI和Telegraf插件将数据写入InfluxDB。
查询数据
将数据写入InfluxDB后,可以使用查询端点执行简单的InfluxDB查询
GET https://127.0.0.1:8086/query
我们可以使用上述API从InfluxDB查询数据;写入数据的语法如下
‘测量值, 标签键 = ’标签值’, 字段键 = ’字段值’, 纪元时间戳‘。
$ curl -G 'https://127.0.0.1:8086/query?db=mydb' --data-urlencode 'q=SELECT * FROM "enginespeed"'
结果可以以以下所示JSON格式检索
"results": [
{
"statement_id": 0,
"series": [
{
"name": "engiespeed",
"columns": [
"time",
"value",
"serialnumber"
],
"values": [
[
"2017-03-01T00:16:18Z",
129,
10001
],
[
"2017-03-01T00:17:18Z",
84,
10001
],
[
"2017-03-01T00:17:18Z",
79,
10001
]
]
}
]
}
]
}
我们也可以在查询中执行所有聚合和分组,以检索所需的数据。一个包含选择和聚合子句的示例查询如下所示
> SELECT MAX("water_level") FROM "h2o_feet" WHERE time >= '2015-08-17T23:48:00Z' AND time <= '2015-08-18T00:54:00Z' GROUP BY time(12m)
name: h2o_feet
tags: location=coyote_creek
time max
---- ---
2015-08-17T23:48:00Z 9.01
2015-08-18T00:00:00Z 8.12
2015-08-18T00:12:00Z 7.887
2015-08-18T00:24:00Z 7.635
这样,我们可以根据需要使用不同的子句执行查询,并以时间序列格式获取数据。如开头所示,可以使用相同的数据通过数据绘制各种图表,这可以用于生成对该数据的更多见解和预测。此外,这些数据还可以用于故障排除和理解指标和事件的流。
在这篇文章中,我试图通过InfluxDB为例,介绍时间序列数据库的什么是、为什么和怎么做。专家们认识到时间序列数据库的兴起需求,我建议更多地了解时间序列,因为以时间序列格式存储您的项目可能是一个变革。
关于作者
Thamatam Vijay Kumar是博世的数据架构师,拥有11年以上的云解决方案和数据管理经验。他热衷于构建解决方案和产品,并渴望为其进行架构设计。他主要参与了云服务和数据管理相关技术的多个项目,并参与了设计、开发和部署解决方案的工作。