Estamos desenvolvendo uma plataforma para cartões pré-pagos, que basicamente contém dados sobre cartões e seus saldos, pagamentos, etc.
Até agora, tínhamos uma entidade do cartão que possui uma coleção de entidades da conta e cada conta tem um valor que é atualizado a cada depósito / retirada.
Há um debate agora na equipe; alguém nos disse que isso infringe as 12 regras do Codd e que atualizar seu valor a cada pagamento é um problema.
Isto é realmente um problema?
Se for, como podemos corrigir isso?
database-design
rdbms
Mithir
fonte
fonte
Respostas:
Sim, isso não é normalizado, mas ocasionalmente projetos não normalizados vencem por razões de desempenho.
No entanto, eu provavelmente abordaria um pouco diferente, por razões de segurança. (Isenção de responsabilidade: atualmente não trabalho, nem nunca trabalhei no setor financeiro. Só estou jogando isso lá fora.)
Tenha uma tabela para os saldos registrados nos cartões. Isso teria uma linha inserida para cada conta, indicando o saldo lançado ao final de cada período (dia, semana, mês ou o que for apropriado). Indexe esta tabela por número de conta e data.
Use outra tabela para manter transações pendentes, que são inseridas em tempo real. No final de cada período, execute uma rotina que inclua as transações não lançadas no último saldo final da conta para calcular o novo saldo. Marque as transações pendentes como lançadas ou verifique as datas para determinar o que ainda está pendente.
Dessa forma, você tem um meio de calcular o saldo do cartão sob demanda, sem precisar resumir todo o histórico da conta e, colocando o recálculo do saldo em uma rotina de lançamento dedicada, pode garantir que a segurança da transação desse recálculo seja limitada a um único local (e também limita a segurança na tabela de saldo, para que somente a rotina de lançamento possa gravar nele).
Depois, basta manter o máximo de dados históricos necessários para auditoria, atendimento ao cliente e requisitos de desempenho.
fonte
Por outro lado, há um problema que encontramos com freqüência no software de contabilidade. Parafraseado:
A resposta, claro, é não, você não. Existem algumas abordagens aqui. Um deles é armazenar o valor calculado. Eu não recomendo esta abordagem porque os bugs de software que causam valores incorretos são muito difíceis de rastrear e, portanto, evitaria essa abordagem.
Uma maneira melhor de fazer isso é o que chamo de abordagem agregação de log-instantâneo. Nessa abordagem, nossos pagamentos e usos são inserções e nunca atualizamos esses valores. Periodicamente, agregamos os dados durante um período de tempo e inserimos um registro de instantâneo calculado que representa os dados no momento em que o instantâneo se tornou válido (geralmente um período de tempo antes do presente).
Agora, isso não viola as regras do Codd porque, com o tempo, os instantâneos podem ser menos do que perfeitamente dependentes dos dados de pagamento / uso inseridos. Se tivermos instantâneos de trabalho, podemos decidir limpar dados com 10 anos de idade sem afetar nossa capacidade de calcular os saldos atuais sob demanda.
fonte
Por razões de desempenho, na maioria dos casos, devemos armazenar o saldo atual - caso contrário, calculá-lo em tempo real pode eventualmente tornar-se proibitivamente lento.
Armazenamos totais de execução pré-calculados em nosso sistema. Para garantir que os números estejam sempre corretos, usamos restrições. A solução a seguir foi copiada do meu blog. Ele descreve um inventário, que é essencialmente o mesmo problema:
O cálculo dos totais em execução é notoriamente lento, seja com um cursor ou com uma junção triangular. É muito tentador desnormalizar, armazenar totais em execução em uma coluna, especialmente se você a selecionar com frequência. No entanto, como sempre, quando você desnormaliza, precisa garantir a integridade de seus dados desnormalizados. Felizmente, você pode garantir a integridade dos totais em execução com restrições - desde que todas as suas restrições sejam confiáveis, todos os totais em execução estejam corretos. Dessa forma, você pode facilmente garantir que o saldo atual (totais em execução) nunca seja negativo - a imposição de outros métodos também pode ser muito lenta. O script a seguir demonstra a técnica.
fonte
Esta é uma pergunta muito boa.
Supondo que você tenha uma tabela de transações que armazene cada débito / crédito, não há nada de errado com seu design. De fato, trabalhei com sistemas de telecomunicações pré-pagos que funcionavam exatamente dessa maneira.
A principal coisa que você precisa fazer é garantir que você esteja fazendo um
SELECT ... FOR UPDATE
saldo enquanto fazINSERT
o débito / crédito. Isso garantirá o saldo correto se algo der errado (porque toda a transação será revertida).Como outros já apontaram, você precisará de uma captura instantânea de saldos em períodos específicos para verificar se todas as transações em um determinado período somam os saldos inicial / final do período corretamente. Escreva um trabalho em lotes que seja executado à meia-noite no final do período (mês / semana / dia) para fazer isso.
fonte
O saldo é um valor calculado com base em certas regras de negócios; portanto, você não deseja manter o saldo, mas calculá-lo a partir das transações no cartão e, portanto, na conta.
Você deseja acompanhar todas as transações no cartão para relatórios de auditoria e extrato e até dados de sistemas diferentes posteriormente.
Bottom line - calcule todos os valores que precisam ser computados como e quando você precisar
fonte