Qual é a maneira mais eficiente de armazenar medições com um número variável de campos em um banco de dados?

StackOverflow https://stackoverflow.com/questions/1629458

  •  06-07-2019
  •  | 
  •  

Pergunta

Temos um sistema de coleta de dados que coleta medições de sensores ambientais que medem a velocidade da água que flui através de um rio ou canal. Cada medição gera um número fixo de valores (por exemplo, hora, tempo, temperatura, pressão etc.) mais uma lista de valores de velocidade.
Originalmente, os sensores forneciam três valores de velocidade, então eu simplesmente armazenei cada valor em sua própria coluna de uma única tabela em um banco de dados Firebird. Posteriormente, foram introduzidos sensores que poderiam produzir até nove valores de velocidade, então eu simples adicionei mais seis colunas. Embora a maioria dos sensores use menos de 9 valores, achei que não seria um problema se a maioria das colunas contivesse zeros.
Mas agora estou enfrentando uma nova geração que pode gerar qualquer coisa de 1 a 256 valores e presumo que não seja muito eficiente adicionar outras 247 colunas, especialmente porque a maioria das medições ainda conterá apenas 3 a 9 valores.
Como as medições são coletadas a cada 10 minutos e o banco de dados contém todos os dados para 30 a 50 sensores, a quantidade total de dados é bastante significativa após alguns anos, mas deve ser possível gerar visões gerais/gráficos por qualquer período aleatório de tempo.

Então, qual seria a maneira mais eficiente de armazenar a lista de valores variável?
Como cada registro possui seu próprio ID, suponho que eu poderia armazenar todos os valores de velocidade em tabela separada, cada valor marcado com o ID do registro. Só tenho a sensação de que isso não seria muito eficiente e que ficaria muito lento depois.

Foi útil?

Solução

Os bancos de dados podem lidar com grandes quantidades de dados em uma tabela se você usar índices eficientes. Então você pode usar esta estrutura de tabela:

create table measurements (
     id,
     seq integer, -- between 1 and 256
     ts timestamp, -- Timestamp of the measurement
     value decimal(...)
)

Criar um índice em id, id, seq e ts. Isso permitirá que você pesquise com eficiência através dos dados. Se você desconfiar do seu banco de dados, basta inserir alguns milhões de linhas e executar algumas seleções para ver como ele se sai.

Para comparação: eu tenho um banco de dados Oracle aqui com 112 milhões de linhas e posso selecionar um registro por registro de data e hora ou ID em 120ms (0,12s)

Outras dicas

Você pode salvar dados serializados em um campo de texto, por exemplo, codificando as medidas como:

[<velocity-value-1>, <velocity-value-2>, ...]

Em seguida, em seu código, desaperialize os valores após a consulta.

Isso deve funcionar bem se você filtrar suas consultas apenas pelos outros campos, e não pelos valores salvos. Se você filtrar pelos valores, usando -os em WHERE As cláusulas serão um pesadelo.

Eu iria com uma segunda mesa:

table measurements (Id, DateTime, Temperature, Pressure)
table velocity (Id, MeasurementId, Sequence, Value)

Velocity.MeasurementId referências Measurements.Id.
Velocity.Sequence é o índice do valor de velocidade para essa medição (1-256).

Preencha essas tabelas com dados o mais próximo possível do mundo real e teste as instruções SQL para encontrar os melhores índices.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top