Armazenando Séries de Dados Temporais em Bases de Dados Alternativas André Carlucci Diretor de Tecnologia Way2.Net MVP, Intel Innovator, Intel Black Belt @andrecarlucci
O que são séries temporais?
Uma série temporal é uma sequência de medições coletadas normalmente em ordem cronológica com um intervalo fixo. Mr. Wikipedia, (2004), TimeSeries
A long time ago in a galaxy far far away
Get the data!
250 Medidores 154 Grandezas (5, 15 ou 60 minutos) 2.5M/registros dia
s Not that much
TB_MEDIDOR Id Medidor Nome Serial TB_MEDIDOR_ENE Id Medidor Timestamp Energia Ativa In Energia Ativa Out Energia Reativa In Energia Reativa Out Mesmo para engenharia, qualidade, etc...
Vida em 2005 Elipse E3 Server Oracle 8i Asp.Net Clássico
Fast Forward 2015
10 anos depois
10 anos depois
200K Medidores 14 Grandezas (5 minutos) 806M/registros dia
s Considerável
Leituras a cada 6 horas: 201M
A forma atual aguenta?
Quebra em Microservices Bulk Insert Way2 PdC Validador DataIn
Repensando a forma de armazenar
Modelo original (tall storage): Timestamp Id Energia Ativa In 1/1/2005 10:00 1/1/2005 10:05 1/1/2005 10:10 Energia Ativa Out Energia Reativa In Energia Reativa Out 13 134.1 0 12.2 0 13 132.7 0 11.2 0 13 132.6 0 14.4 0
Modelo original (tall storage): The Bad: Locks com inserção paralela de grandezas Timestamp Id Energia Insert or update Ativa In Ruim para bulk insert 1/1/2005 10:00 1/1/2005 10:05 1/1/2005 10:10 Energia Ativa Out Energia Reativa In Energia Reativa Out 13 134.1 0 12.2 0 13 132.7 0 11.2 0 13 132.6 0 14.4 0
Wide Storage, por grandeza: Id Day 00:05 00:10 00:15 1 1/1/2016 0 12.2 0 1 2/1/2016 0 11.2 0 1 3/1/2016 0 14.4 0
Modelo Wide The Bad: Storage, original por (tall grandeza: storage): Complexidade de inserts, queries e group by. Timestamp Id Id Day Energia 00:05 Energia 00:10 Energia 00:15 Energia Não suporta integralizações 1 1/1/2016Ativa In 0Ativadiferentes. Out 12.2 Reativa In Reativa 0 Out Ruim para bulk insert 1/1/2005 1 13 2/1/2016 134.1 0 0 11.212.2 00 10:00 1/1/2005 1 13 3/1/2016 132.7 0 0 14.411.2 00 10:05 1/1/2005 13 132.6 0 14.4 0 10:10
Tall Storage, por grandeza, por ano: Timestamp Id Valor 1/1/2005 10:00 1 134.1 1/1/2005 10:05 1 132.7 1/1/2005 10:10 1 132.6 Tb_EnergiaAtiva_2015, Tb_EnergiaAtiva_2016
Modelo Tall Wide Storage, original por por (tall grandeza, grandeza: storage): por ano: Nossa Escolha em termos de sql: Timestamp Id Id Day Energia 00:05 Energia 00:10 Energia 00:15 Energia Simples Timestamp 1 1/1/2016Ativa In Id 0Ativa Out 12.2 ReativaValor In Reativa 0 Out Bulk 1/1/2005 Insert 10:00 sem medo 1 134.1 1/1/2005 1 13 2/1/2016 134.1 0 0 11.212.2 00 10:00 Sem locks nos inserts 1/1/2005 10:05 1 132.7 1/1/2005 Tabelas 1 auto-criadas 13 3/1/2016 132.7 0 0 14.411.2 00 10:05 Backup 1/1/2005 10:10 e restore super 1 simples 132.6 1/1/2005 13 132.6 0 14.4 0 10:10 Tamanho das tabelas controlados ($)
TB_Medidor Id Medidor Serial TB_EnergiaAtiva Id Medidor Timestamp Valor Relacionamento entre Tabelas
TB_Medidor Id Medidor Serial TB_EnergiaAtiva Id Medidor Timestamp Valor Ganho de 28.7%
Separação das Bases Sql? Dados Relacionais Séries de Dados
Restrições
Bases de Dados Analisadas
4th base mais popular* Apache License Orientada a documentos *http://db-engines.com/en/ranking
Estratégia 1: Um documento por medição
{ }, { } timestamp: ISODate("2015-11-10T23:05:00.000Z"), id: 100 type: "energiaativa", value: 12 timestamp: ISODate("2015-11-10T23:10:00.000Z"), id: 100 type: "energiaativa", value: 14 somente inserts
Estratégia 2: Schema orientado a documentos
{ } day: ISODate("2015-10-10T00:00:00.000Z"), type: "energiaativa", id : 100, values: { 1: { 0: 200, 1: 200,, 12: 100 },, 23: { 0: 160, 1: 120,, 12: 110 }, 24: { 0: 130, 1: 140,, 12: 150 } }
db.metrics.update( { day: ISODate("2013-10-10T00:00:00.000Z"), id: 100, type: "energiaativa" }, { $set: {"values.10.01": 193 } } ) update preciso
Reads: Estratégia 1: 288 reads (dia) Estratégia 2: 1 read (dia)
Otimizações: Ter um job criando documentos vazios Definir ID como {timestamp}_{id} para range scans
Nossas impressões: Developer Friendly Instalação Simples Sharding Maduro
Base de dados feita para Séries de Dados
API - Write HTTP POST: http://localhost:8086/write?db=mydb' EneatDel,Med=102 value=632.0 1420070400 EneatDel,Med=102 value=632.0 1420070700
API - Read HTTP GET: http://localhost:8086/query?db=mydb&q= SELECT value FROM EneatDel WHERE Med=102
Regras para retenção de dados Dados Delete dados com mais de um ano
Séries contínuas 5 MIN Agrupe dados por hora 1 DIA
Nossas impressões API Simples Queries poderosas Funcionalidades específicas Sharding (free até v0.11, depois pago) Imaturo ainda (v0.11, windows)
Outras alternativas Druid SiteWhere Newts Prometheus Graphite Axibase Infiniflux KairosDB Kdb+ Yanza Riak TS OpenTSDB Blueflood Cityzen Data TempoIQ Hawkular Metrics TimeSeries.Guru
Descrição Bytes DateStart 8 DateEnd 8 Current 8 Interval 4 Valor 1 8 Valor 2 8 Valor 3 8 28 bytes N * 8 bytes 28 + (288 * 365d * 8) bytes = 821kB
API - Read GET: http://localhost/list?{id}&{inicio}&{fim}
API - Write POST: http://localhost/add/{id} { Data: 2015-01-01T00:05, Value: 100 },
Query: Id: med/12/energiaativa Inicio: 30/03/2016 Fim: 31/03/2016
Query: ache o arquivo Id: med/12/energiaativa Arquivo: c:\neutrino\db\med\12\energiaativa.ts
Query: ache o primeiro registro Pesquisa Início - Início Arquivo Intervalo Arquivo = Registros a pular
Query: ache o primeiro registro Header (28 bytes) 8B 8B 8B 8B 8B 8B 8B 8B 8B 8B 8B Registros a pular
Query: ache o número de registros (Fim início) / Intervalo Arquivo: 31/03/2016-30/01/2016 / 5min = 288
var data = new byte[registros * sizeof(double)]; var fs = new FileStream(path); fs.seek(offset); fs.readasync(data, 0, data.length); return Deserialize(data);
Nossas impressões Customizado Backup ultra simples Pouco espaço de armazenamento Pode ser incorporado a aplicação (C#) Ainda um experimento!!!
Storage Oracle Antigo Oracle Mongodb Influxdb Neutrino Medidor/Ano 8 MB 3.5 MB 1.9 MB 1.3 MB 0.8 MB 200K, 14 séries 106 TB 47 TB 25 TB 17 TB 10 TB
Conclusões Trate series de dados como series de dados.
Conclusões Influxdb nos pareceu a melhor opção, mas há muitas incertezas ainda.
Conclusões Apesar de tudo, um banco relacional continua sendo uma excelente opção, pois nem sempre a decisão é somente técnica.
Perguntas? André Carlucci Diretor de Tecnologia Way2.Net MVP, Intel Innovator, Intel Black Belt @andrecarlucci
Obrigado! André Carlucci Diretor de Tecnologia Way2.Net MVP, Intel Innovator, Intel Black Belt @andrecarlucci