Armazenando Séries de Dados Temporais em Bases de · PDF fileKairosDB Druid Riak TS...

Preview:

Citation preview

Armazenando Séries de Dados Temporais em Bases de Dados Alternativas

André CarlucciDiretor 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

sNot that much

TB_MEDIDOR_ENE

Id Medidor

Timestamp

Energia Ativa In

Energia Ativa Out

Energia Reativa In

Energia Reativa Out

TB_MEDIDOR

Id Medidor

Nome

Serial

Mesmo para engenharia, qualidade, etc...

Elipse E3 Server Oracle 8i

Vida em 2005

Asp.Net Clássico

Fast Forward 2015

10 anos depois

10 anos depois

200K Medidores

14 Grandezas (5 minutos)

806M/registros dia

sConsiderável

Leituras a cada 6 horas:

201M

A forma atual aguenta?

Way2 PdC Validador

Quebra em Microservices

DataIn

Bulk Insert

Repensando a forma de

armazenar

Timestamp Id Energia

Ativa In

Energia

Ativa Out

Energia

Reativa In

Energia

Reativa

Out

1/1/2005

10:00

13 134.1 0 12.2 0

1/1/2005

10:05

13 132.7 0 11.2 0

1/1/2005

10:10

13 132.6 0 14.4 0

… … … … …

Modelo original (tall storage):

Timestamp Id Energia

Ativa In

Energia

Ativa Out

Energia

Reativa In

Energia

Reativa

Out

1/1/2005

10:00

13 134.1 0 12.2 0

1/1/2005

10:05

13 132.7 0 11.2 0

1/1/2005

10:10

13 132.6 0 14.4 0

… … … … …

Modelo original (tall storage):The Bad:

Locks com inserção paralela de grandezas

Insert or update

Ruim para bulk insert

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

… … … … …

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

… … … … …

Wide Storage, por grandeza:

Timestamp Id Energia

Ativa In

Energia

Ativa Out

Energia

Reativa In

Energia

Reativa

Out

1/1/2005

10:00

13 134.1 0 12.2 0

1/1/2005

10:05

13 132.7 0 11.2 0

1/1/2005

10:10

13 132.6 0 14.4 0

… … … … …

Modelo original (tall storage):The Bad:

Complexidade de inserts, queries e group by.

Não suporta integralizações diferentes.

Ruim para bulk insert

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

… … …

Tall Storage, por grandeza, por ano:

Tb_EnergiaAtiva_2015, Tb_EnergiaAtiva_2016…

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

… … …

Tall Storage, por grandeza, por ano:

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

… … … … …

Wide Storage, por grandeza:

Timestamp Id Energia

Ativa In

Energia

Ativa Out

Energia

Reativa In

Energia

Reativa

Out

1/1/2005

10:00

13 134.1 0 12.2 0

1/1/2005

10:05

13 132.7 0 11.2 0

1/1/2005

10:10

13 132.6 0 14.4 0

… … … … …

Modelo original (tall storage):Nossa Escolha em termos de sql:

Simples

Bulk Insert sem medo

Sem locks nos inserts

Tabelas auto-criadas

Backup e restore super simples

Tamanho das tabelas controlados ($)

TB_EnergiaAtiva

Id Medidor

Timestamp

Valor

TB_Medidor

Id Medidor

Serial

Relacionamento entre Tabelas

28.7%Ganho de

TB_EnergiaAtiva

Id Medidor

Timestamp

Valor

TB_Medidor

Id Medidor

Serial

Dados Relacionais Séries de Dados

Separação das Bases

Sql?

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: 100type: "energiaAtiva",value: 12

},{

timestamp: ISODate("2015-11-10T23:10:00.000Z"),id: 100type: "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 1420070400EneatDel,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

Graphite

OpenTSDB

KairosDB

Druid

Riak TS

TempoIQ

Blueflood

Cityzen Data

Hawkular Metrics

Newts

TimeSeries.Guru

SiteWhere

Axibase

Infiniflux Yanza

Kdb+

Prometheus

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

},…

Id: med/12/energiaAtivaInicio: 30/03/2016Fim: 31/03/2016

Query:

Id:med/12/energiaAtiva

Query: ache o arquivo

Arquivo: c:\neutrino\db\med\12\energiaAtiva.ts

Query: ache o primeiro registro

PesquisaInício

InícioArquivo

-

IntervaloArquivo

Registrosa 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éries106 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é CarlucciDiretor de Tecnologia – Way2

.Net MVP, Intel Innovator, Intel Black Belt

@andrecarlucci

Obrigado!

André CarlucciDiretor de Tecnologia – Way2

.Net MVP, Intel Innovator, Intel Black Belt

@andrecarlucci

Recommended