Usando uma chave natural, ou usar chaves substitutas e tabela de auditoria (s) para auditoria de log / mudança

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

Pergunta

A minha primeira pergunta aqui assim que seja bom!

Eu sou um desenvolvedor júnior com não muita experiência e estou tendo problemas com este problema.

Eu tenho uma tabela que precisa ser auditável. Digamos esta tabela registra chamadas telefônicas feitas por um call center (não é, mas é apenas um exemplo). Eu vou chamá-lo de "CallHistory".

Eu tinha planejado originalmente para manter uma tabela separada chamada "Chamados", que tem o nome dos callees, número de telefone, etc. Esta tabela estaria usando uma chave primária substituto.

A tabela CallHistory teria uma chave estrangeira para a tabela Callee.

Eu originalmente fez isso para que se eu mudasse número de telefone do destinatário da chamada, seria propagar por todo o sistema e eu não teria que mudar o número de telefone em várias tabelas.

O problema é que todo o ponto da tabela de CallHistory é para gravar o histórico de chamadas, incluindo chamadas de mis-marcados (digamos, um chamador discou o número errado). A história seria perdido usando esta abordagem chave substituta.

Um dos desenvolvedores seniores no trabalho sugeriu manter cópias do número de telefone para cada discagem de um chamador naquele momento específico na tabela CallHistory para preservar a história.

Eu estava pensando sobre como manter uma tabela log de auditoria / mudança para o mesmo fim.

Será que a minha abordagem bastam para este purpsose ou estou totalmente fora da pista? Que abordagem você prefere?

Cheers, Andrew

Foi útil?

Solução

Eu concordo com Rik. Sim, dados redundantes é muito, muito mau, mal, mau cheiro, e de outra forma indesejável. Mas só porque dois campos são chamados de "número de telefone" não lhes faz a mesma coisa. "O número de cliente atual de telefone" e "número de telefone do cliente no momento em que a última vez que falou com ele" não são necessariamente a mesma coisa.

Estou atualmente trabalhando com um banco de dados que mantém venda e item de informação. Um registro de item inclui informações como descrição, número de estoque e preço. Nossos registros venda também incluem descrição, número de estoque e preço. Descrição e número de estoque são redundantes e devem ser eliminadas. Este foi mau design. Mas o preço deve ser incluído em ambos os lugares. Há uma grande diferença entre o preço atual eo preço no momento de uma dada venda. Que a venda poderia ter sido anos atrás. O preço pode ter mudado uma dúzia de vezes desde então.

Em geral, em uma aplicação como você descreve eu tinha acabado de colocar o número de telefone na tabela de história e ser feito com ele. Há pouco a ser adquirida por ter uma tabela "número de telefone história" e ligando para o registro número de telefone aplicável-at-a-time. Ele pode economizar alguns bytes por registro, mas gostaria de acrescentar um monte de complexidade. No entanto, se existem vários campos relacionados, a história muda. Se, por exemplo - e eu estou apenas inventando um exemplo aqui para dar a idéia - você é uma empresa de seguro de saúde e seus termos de cobertura variam dependendo do local devido a diferentes leis estaduais, médicos disponíveis na área, etc, de modo que quando um cliente se move sua política deve ser reescrita, agora número de telefone pode estar relacionado com muitos outros itens de dados, e então tudo deve ir em uma única mesa e você link para o registro adequado. Caso contrário, você pode ter um número de telefone de Nova Jersey, mas você está ligando para termos políticos Califórnia, etc.

Outras dicas

Eu acho que você está sendo enganado por uma sutileza sobre as formas normais aqui. A coisa é, o número de telefone associado com o receptor é não é o mesmo pedaço de informação como o número discado pelo chamador. Eles podem ter o mesmo valor no caso geral, mas isso é outra questão.

Então, na minha opinião, CallHistory deve ter tanto o numbre discado e uma referência para a mesa o receptor.

A sua pergunta é muito típico dilema design. Por exemplo, se você tem banco de dados na forma normal, e você tem os seguintes quadros: vendas, gerentes (que vende) e regiões (onde os gestores estão trabalhando). Você está construindo relatórios como "vendas anuais agrupados por regiões" onde juntando vendas com gestores e gerentes com as regiões. Mas se um dos gerentes vai mudar para outro escritório durante o ano, parece que o seu relatório mostrará dados incorretos, certo?

O que são 3 soluções

1) Em alguns casos, os desenvolvedores e analista decidir: bem, os nossos dados não é muito correto, mas é OK para agora, nós queremos ficar com a forma normal e não dados duplicados. Esta solução é menos complexo. Neste caso, você pode criar tabelas chamadores e CallHistory em forma normal, ou seja, número de telefone será na única mesa de chamadores.

2) Há uma exigência para não perder quaisquer mudanças históricas. E queremos que os nossos relatórios e consultas ser muito rápido (ao custo de tamanho de banco de dados). Neste caso, as pessoas decidem duplicar todos os campos. Por exemplo, você pode criar a tabela CallHistory que tem o número de telefone, nome chamadores, endereço etc., porque você antecipar que cada um destes campos pode ser alterado no futuro. Claro que você pode criar Callee mesa bem (provavelmente você vai precisar dele para outros fins), mas pode ser reefenced por CallHistory e pode não ser. Suponha que você acha que alguns registros precisam ser excluído do Callee mas quer que eles sejam em CallHistory. Este é o caso quando os desenvolvedores muitas vezes pensam que podem violar a integridade referencial dos dados, não crie nenhum chaves estrangeiras da tabela CallHistory. E isso é razoável, porque sem chaves estrangeiras, inserções vai trabalhar mais rápido.

3) abordagem que eu gosto mais, mas é mais complexo do ponto de vista da implementação: mesa CallHistory deve fazer referência à tabela CalleeHistory. mesa CalleeHistory terá todos fileds que a tabela Callee tem, mas também tem uma chave substituta, como CalleeID + DateModified (às vezes em vez de desenvolvedores DateModified usam ModificationVersionNumber). Em CallHistory temos uma chave estrangeira substituto essa referência CalleeID + DateModified. Neste caso você tenha normalizado de dados (ou seja, número de telefone não é dublicated em tabelas diferentes), e também você didnt perder quaisquer mudanças históricas.

Tanto quanto eu disse, muitas vezes há um trade-off entre a complexidade de implementação, o desempenho do banco de dados, o tamanho do banco de dados, integridade dos dados e requisitos funcionais do sistema. Se você é um desenvolvedor júnior, é bom ter em mente todas as soluções possíveis, mas provavelmente você deve ouvir um desenvolvedor sênior, quem sabe sobre o seu sistema e os requisitos de mais do que ninguém no Stack Overflow.

P.S.

Se você quer saber sobre outras abordagens, leia sobre dimensões mudando lentamente, por exemplo http: // en.wikipedia.org/wiki/Slowly_changing_dimension

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