Yet Another TimeSeries Database是受InfluxDb和RavenDB启发的实验性时间序列数据库。
YATsDb 采用纯.NET和现代C#实现,具有出色的性能(在 Intel i7-8550U CPU、1.80GHz、24GB RAM、SSD 上每秒插入约 30K - 一次插入一行)。
我需要一个用于家庭 IoT 项目的时间序列数据库,但使用InfluxDb会很无聊。原型的实现只花了 12 个小时,它知道如何输入数据并进行查询。
YATsDb是一个完整的数据库实现,具有 GUI、OpenAPI 定义和作业。它需要 .NET 8 运行时才能运行。
YATsDb.Lite是具有核心时间序列数据库功能的 AOT 编译版本。它不依赖于目标系统。
生成的二进制文件相对较小< 15MB 。
以下是使用 cURL 来使用YATsDb/YATsDb.Litle的示例( YATsDb还提供了 OpenAPI 端点定义)。
在示例中,基本 URL 是 http://localhost:8080/。
创建一个新存储桶smart_home
:
curl -XPOST http://localhost:8080/management/bucket --header " Content-Type: application/json " --data-binary " { " bucketName " : " smart_home " , " description " : null} "
以简单行格式输入样本数据( <measurement>[,<tag>] <value>[,<value>...n] [<timestampInMs>]
),此格式受到InfluxDb的启发,但不使用命名值,但是位置值。此外,在InfluxDb之前,始终使用以毫秒为单位的 unix 时间戳作为时间。
以下示例数据代表传感器家庭测量的数据 - 温度、湿度、光强度。
curl -XPOST http://localhost:8080/write/smart_home --data-binary " sensors_data,Room1 22.0,45,80.4 1719242779202 "
curl -XPOST http://localhost:8080/write/smart_home --data-binary " sensors_data,Room1 23.1,39.4,75.0 1719243079200 "
curl -XPOST http://localhost:8080/write/smart_home --data-binary " sensors_data,Room1 23.2,41.7,NULL 1719243379246 "
curl -XPOST http://localhost:8080/write/smart_home --data-binary " sensors_data,Room2 23.0,41,80.4 1719243379256 "
curl -XPOST http://localhost:8080/write/smart_home --data-binary " sensors_data,Room1 22.0,45,80.4 1719243679194 "
curl -XPOST http://localhost:8080/write/smart_home --data-binary " sensors_data,Room2 22.7,47.4,NULL 1719243979257 "
curl -XPOST http://localhost:8080/write/smart_home --data-binary " sensors_data,Room1 22.1,47,NULL 1719244279035 "
curl -XPOST http://localhost:8080/write/smart_home --data-binary " sensors_data,Room3 18.7,NULL,NULL 1719244579031 "
curl -XPOST http://localhost:8080/write/smart_home --data-binary " sensors_data,Room1 24.7,51.7,2.4 1719244879109 "
可以在一条消息中发送多行,但并非每个 shell 都支持这一点。
curl -XPOST http://localhost:8080/write/smart_home --data-binary " sensors_data,Room1 24.7,51.7,2.4 1719244879109
sensors_data,Room1 24.8,55.7,3.9 1719244899109 "
YATsDb允许使用类似于 SQL 的语法进行查询,但使用值位置而不是名称。查询的结果是 JSON 结果。
选择Room2超过 12 小时的湿度数据:
curl -XPOST http://localhost:8080/query/raw/smart_home --data-binary " SELECT AVG(1), MIN(1), MAX(1), COUNT(1) FROM sensors_data WHERE TAG('Room2') AND INTERVAL(NULL, -10h) GROUP BY +10m "
插入数据数据的完整语法-简单线路协议:
<lines> ::= <line> [ [r]n...n ]
<line> ::= <measurement> <values> [<timestamp>]
<measurement> ::= measurement_name [, tag]
<values> ::= <value> [, ...250]
<value> ::={ double_value | NULL }
<timestamp> ::= unix timestamp in milliseconds
无标签测量:
sensors_data 12.5 1608852317000
带标签测量:
sensors_data,home/room3/esp32 12.5 1608852317000
多值测量:
sensors_data,home/room3/esp32 12.5,-14.3,89,47.0036 1608852317000
缺失值的测量(对于缺失值使用NULL
):
sensors_data,home/room4/esp32 12.5,NULL,89,47.0036 1608852317000
没有 unix 时间戳的测量 - 使用当前服务器时间:
sensors_data,home/room3/esp32 12.5
多行值:
sensors_data,home/room3/esp32 12.5 1608852317000
pc_data,Workstation1 25.78,47.5,236566 1608852317900
sensors_data,home/room3/esp32 13.5 1608852417000
查询数据的完整语法:
<SELECT statement> ::= SELECT <projection statement> FROM measurement_name
[<WHERE statement>]
[<GROUPBY statement>]
[<LIMIT statement>]
<projection statement> ::= { * | <projection> [ ,...250 ]}
<projection> ::= <projection function>(<index>)
<projection function> ::= { VARIANCE | SUM | COUNT | AVG | IDENTITY | MAX | MIN | STDDEV | REMEDIAN | SIGN | CHANGE_PER_SEC | CHANGE_PER_HOUR | CHANGE_PER_DAY }
<index> ::= integer_number
<WHERE statement> ::= WHERE <where function> [AND ...n]
<where function> ::= { TAG(<string>) | INTERVAL(<interval exp>, <interval exp>) }
<string> ::= string
<interval exp> ::= { integer_number | <time span> | <string> | NOW() }
<time span> ::= { + | - }double_value{ ms | s | m | h | d | w | y }
<GROUPBY statement> ::= GROUP BY <time span>
<LIMIT statement> ::= LIMIT { integer_number | integer_number, integer_number | ..integer_number }
选择所有数据:
SELECT * FROM sensors_data
从Room3中选择前 5 条记录:
SELECT * FROM sensors_data WHERE TAG('Room3') LIMIT 0,5
按10分钟选择温度数据组:
SELECT AVG(0), MIN(0), MAX(0) FROM sensors_data GROUP BY +10m
从Room2选择湿度数据:
SELECT AVG(1), MIN(1), MAX(1), COUNT(1) FROM sensors_data WHERE TAG('Room2') GROUP BY +1d
选择Room2超过 12 小时的湿度数据:
SELECT AVG(1), MIN(1), MAX(1), COUNT(1) FROM sensors_data WHERE TAG('Room2') AND INTERVAL(NULL, -12h) GROUP BY +10m
选择最后一条记录:
SELECT * FROM sensors_data LIMIT ..1
对所有数据进行分组:
SELECT AVG(0), AVG(1), AVG(2) FROM sensors_data
按具体时间选择(使用以毫秒为单位的unix时间戳):
SELECT AVG(0), COUNT(0) FROM sensors_data WHERE INTERVAL(1603519860000, 1608852317000) GROUP BY +10m
按具体时间选择(使用人类可读的时间):
SELECT AVG(0), COUNT(0) FROM sensors_data WHERE INTERVAL('2012-06-12 08:33:12.478', '2012-06-13') GROUP BY +10m