Versioned e armazenamento de dados indexada
-
19-09-2019 - |
Pergunta
Eu tenho um requisito para armazenar todas as versões de uma entidade de uma forma facilmente indexado e queria saber se alguém tem informações sobre o que sistema para uso.
Sem controle de versão do sistema é simplesmente um banco de dados relacional com um por linha, por exemplo, pessoa. Se o estado da pessoa muda essa linha é alterado para refletir isso. Com versões a entrada deve ser atualizado de tal maneira um modo que podemos sempre voltar para uma versão anterior. Se eu pudesse usar um banco de dados temporais isso seria livre e eu seria capaz de perguntar: 'qual é o estado de todas as pessoas a partir de ontem às 2h de estar em Dublin e envelhecido 30'. Infelizmente, não parece haver qualquer amadurecer projetos de código aberto que pode fazer temporal.
Uma maneira realmente desagradável de fazer isso é apenas para inserir uma nova linha por alteração de estado. Isto leva a duplicação, como uma pessoa pode ter muitos campos, mas apenas uma mudança por atualização. Também é então bastante lento para selecionar a versão correta para cada pessoa dado um timestamp.
Em teoria, deveria ser possível usar um banco de dados relacional e um sistema de controle de versão para um banco de dados temporais imitar, mas isso soa muito horrendo.
Então, eu queria saber se alguém tem se deparar com algo semelhante antes e como eles se aproximaram dele?
Atualizar Como sugerido por Aaron aqui está a consulta usamos atualmente (em mysql). É definitivamente lento em nossa mesa com> 200k linhas. (Id = chave da tabela, person_id = id por pessoa, duplicada se a pessoa tem muitas revisões)
selecione o nome de pessoa p onde p.id = (select max (id) de pessoa onde person_id = p.person_id e timestamp <=: timestamp)
Atualizar Parece que a melhor maneira de fazer isso é com um db temporal, mas dado que não há qualquer fonte as abertas lá fora, a próxima melhor método é armazenar uma nova linha per atualização. O único problema é a duplicação de colunas inalteradas e uma consulta lenta.
Solução
Há duas maneiras de lidar com isso. Ambos assumem que você sempre inserir novas linhas. Em todos os casos, você deve inserir um timestamp (created
) que lhe diz quando uma linha foi "modificada".
A primeira abordagem usa um número para contar quantos casos você já tem. A chave primária é a chave objeto mais o número versão. O problema com essa abordagem parece ser que você precisará de um select max(version)
fazer uma modificação. Na prática, isso raramente é um problema, uma vez para todas as atualizações do aplicativo, você deve primeiro carregar a versão atual da pessoa, modificá-lo (e incrementar a versão) e, em seguida, inserir a nova linha. Portanto, o problema real é que este projeto faz com que seja difícil de executar atualizações no banco de dados (por exemplo, atribuir uma propriedade para muitos usuários).
A próxima abordagem usa links no banco de dados. Em vez de uma chave composta, você dá a cada objeto uma nova chave e você tem um campo replacedBy
que contém a chave da próxima versão. Esta abordagem torna mais simples para encontrar a versão atual (... where replacedBy is NULL
). As atualizações são um problema, embora, desde que você deve inserir uma nova linha e atualizar um já existente.
Para resolver isso, você pode adicionar um ponteiro de volta (previousVersion
). Dessa forma, você pode inserir as novas linhas e, em seguida, usar o ponteiro de volta para atualizar a versão anterior.
Outras dicas
Aqui está uma (um pouco datado) levantamento da literatura nas bases de dados temporais: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.91.6988&rep=rep1&type=pdf
Eu recomendaria passar um bom tempo sentado com essas referências e / ou Google Scholar para tentar encontrar algumas boas técnicas que se encaixam no seu modelo de dados. Boa sorte!