Yet Another TimeSeries Database é um banco de dados experimental de série temporal inspirado no InfluxDb e RavenDB .
YATsDb é implementado em .NET puro e C# moderno com ótimo desempenho (cerca de 30 mil inserções por segundo na CPU Intel i7-8550U, 1,80 GHz, 24 GB de RAM, SSD - inserindo linhas uma de cada vez).
Eu precisava de um banco de dados de série temporal para projetos domésticos de IoT, mas usar o InfluxDb seria chato. A implementação do protótipo, que sabia inserir dados e fazer consultas, levou apenas 12 horas.
YATsDb é uma implementação completa de banco de dados com GUI, definições e trabalhos OpenAPI. Requer tempo de execução do .NET 8 para ser executado.
YATsDb.Lite é uma versão compilada AOT com funcionalidade central de banco de dados de série temporal. Não tem dependências de sistemas de destino.
O binário resultante é relativamente pequeno <15MB .
A seguir está um exemplo de uso de YATsDb/YATsDb.Litle usando cURL ( YATsDb também fornece uma definição de endpoint OpenAPI).
Nos exemplos, a URL base é http://localhost:8080/.
Crie um novo intervalo smart_home
:
curl -XPOST http://localhost:8080/management/bucket --header " Content-Type: application/json " --data-binary " { " bucketName " : " smart_home " , " description " : null} "
Insira dados de amostra em formato de linha simples ( <measurement>[,<tag>] <value>[,<value>...n] [<timestampInMs>]
), este formato é inspirado em InfluxDb , mas não usa valores nomeados , mas valores posicionais. Além disso, antes de InfluxDb , o carimbo de data/hora unix em milissegundos é sempre usado como hora.
Os dados de amostra a seguir representam dados de medição doméstica de sensores – temperatura, umidade, intensidade de luz.
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 "
É possível enviar múltiplas linhas em uma mensagem, mas nem todo shell suporta isso.
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 permite consultas em uma sintaxe semelhante a SQL, mas usa posições de valor em vez de nomes. O resultado da consulta é um resultado JSON.
Selecione dados de umidade da Sala2 com mais de 12 horas:
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 "
Gramática completa para inserção de dados - protocolo de linha simples:
<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
Medição sem etiqueta:
sensors_data 12.5 1608852317000
Medição com etiqueta:
sensors_data,home/room3/esp32 12.5 1608852317000
Medição com vários valores:
sensors_data,home/room3/esp32 12.5,-14.3,89,47.0036 1608852317000
Medição com valores faltantes (use NULL
para valor faltante):
sensors_data,home/room4/esp32 12.5,NULL,89,47.0036 1608852317000
Medição sem carimbo de data/hora unix - a hora atual do servidor é usada:
sensors_data,home/room3/esp32 12.5
Valores multilinha:
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
Gramática completa para consulta de dados:
<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 }
Selecione todos os dados:
SELECT * FROM sensors_data
Selecione os primeiros 5 registros da Room3 :
SELECT * FROM sensors_data WHERE TAG('Room3') LIMIT 0,5
Selecione o grupo de dados de temperatura em 10 minutos:
SELECT AVG(0), MIN(0), MAX(0) FROM sensors_data GROUP BY +10m
Selecione os dados de umidade da Sala2 :
SELECT AVG(1), MIN(1), MAX(1), COUNT(1) FROM sensors_data WHERE TAG('Room2') GROUP BY +1d
Selecione dados de umidade da Sala2 com mais de 12 horas:
SELECT AVG(1), MIN(1), MAX(1), COUNT(1) FROM sensors_data WHERE TAG('Room2') AND INTERVAL(NULL, -12h) GROUP BY +10m
Selecione o último registro:
SELECT * FROM sensors_data LIMIT ..1
Agrupe todos os dados:
SELECT AVG(0), AVG(1), AVG(2) FROM sensors_data
Selecione por tempo concreto (usando carimbo de data/hora unix em milissegundos):
SELECT AVG(0), COUNT(0) FROM sensors_data WHERE INTERVAL(1603519860000, 1608852317000) GROUP BY +10m
Selecione por tempo concreto (usando tempo legível por humanos):
SELECT AVG(0), COUNT(0) FROM sensors_data WHERE INTERVAL('2012-06-12 08:33:12.478', '2012-06-13') GROUP BY +10m