Estamos desarrollando una plataforma para tarjetas prepagas, que básicamente contiene datos sobre tarjetas y su saldo, pagos, etc.
Hasta ahora teníamos una entidad de Tarjeta que tiene una colección de entidad de Cuenta, y cada Cuenta tiene un Monto, que se actualiza en cada Depósito / Retiro.
Hay un debate ahora en el equipo; alguien nos ha dicho que esto rompe las 12 Reglas de Codd y que actualizar su valor en cada pago es un problema.
¿Es esto realmente un problema?
Si es así, ¿cómo podemos solucionar esto?
database-design
rdbms
Mithir
fuente
fuente
Respuestas:
Sí, eso no está normalizado, pero en ocasiones los diseños no normalizados ganan por razones de rendimiento.
Sin embargo, probablemente lo abordaría de manera un poco diferente, por razones de seguridad. (Descargo de responsabilidad: actualmente no, ni he trabajado en el sector financiero. Solo estoy lanzando esto por ahí).
Tenga una tabla para los saldos publicados en las tarjetas. Esto tendría una fila insertada para cada cuenta, indicando el saldo registrado al cierre de cada período (día, semana, mes o lo que sea apropiado). Indice esta tabla por número de cuenta y fecha.
Use otra tabla para mantener las transacciones pendientes, que se insertan sobre la marcha. Al cierre de cada período, ejecute una rutina que agregue las transacciones no publicadas al último saldo de cierre de la cuenta para calcular el nuevo saldo. Marque las transacciones pendientes como publicadas, o mire las fechas para determinar qué está pendiente.
De esta manera, tiene un medio para calcular el saldo de la tarjeta a pedido, sin tener que resumir todo el historial de la cuenta, y al poner el recálculo del saldo en una rutina de contabilización dedicada, puede asegurarse de que la seguridad de la transacción de este recálculo se limite a un solo lugar (y también limitan la seguridad en la tabla de balance para que solo la rutina de contabilización pueda escribirle).
Luego, conserve la mayor cantidad de datos históricos que requiera la auditoría, el servicio al cliente y los requisitos de rendimiento.
fuente
Por otro lado, hay un problema que encontramos con frecuencia en el software de contabilidad. Parafraseado:
La respuesta, por supuesto, es no, no lo haces. Hay algunos enfoques aquí. Uno está almacenando el valor calculado. No recomiendo este enfoque porque los errores de software que causan valores incorrectos son muy difíciles de rastrear, por lo que evitaría este enfoque.
Una mejor manera de hacerlo es lo que yo llamo el enfoque agregado de registro de instantáneas. En este enfoque, nuestros pagos y usos son insertos y nunca actualizamos estos valores. Periódicamente agregamos los datos durante un período de tiempo e insertamos un registro de instantánea calculado que representa los datos en el momento en que la instantánea se hizo válida (generalmente un período de tiempo antes del presente).
Ahora, esto no rompe las reglas de Codd porque con el tiempo las instantáneas pueden ser menos que perfectamente dependientes de los datos de pago / uso insertados. Si tenemos instantáneas de trabajo, podemos decidir purgar datos de 10 años sin afectar nuestra capacidad de calcular los saldos actuales bajo demanda.
fuente
Por razones de rendimiento, en la mayoría de los casos debemos almacenar el saldo actual; de lo contrario, calcularlo sobre la marcha puede llegar a ser extremadamente lento.
Almacenamos totales acumulados precalculados en nuestro sistema. Para garantizar que los números sean siempre correctos, utilizamos restricciones. La siguiente solución ha sido copiada de mi blog. Describe un inventario, que es esencialmente el mismo problema:
Calcular los totales acumulados es notoriamente lento, ya sea que lo haga con un cursor o con una unión triangular. Es muy tentador desnormalizar, almacenar totales acumulados en una columna, especialmente si lo selecciona con frecuencia. Sin embargo, como es habitual cuando se desnormaliza, debe garantizar la integridad de sus datos desnormalizados. Afortunadamente, puede garantizar la integridad de los totales acumulados con restricciones: siempre y cuando todas sus restricciones sean confiables, todos sus totales acumulados son correctos. También de esta manera puede asegurarse fácilmente de que el saldo actual (totales acumulados) nunca sea negativo: la aplicación por otros métodos también puede ser muy lenta. El siguiente script demuestra la técnica.
fuente
Esta es una muy buena pregunta.
Suponiendo que tiene una tabla de transacciones que almacena cada débito / crédito, su diseño no tiene nada de malo. De hecho, he trabajado con sistemas de telecomunicaciones prepagos que han funcionado exactamente de esta manera.
Lo principal que debe hacer es asegurarse de que está haciendo una parte
SELECT ... FOR UPDATE
del saldo mientras realizaINSERT
el débito / crédito. Esto garantizará el saldo correcto si algo sale mal (porque la transacción completa se revertirá).Como otros han señalado, necesitará una instantánea de los saldos en períodos de tiempo específicos para verificar que todas las transacciones en un período determinado sumen los saldos de inicio / fin del período correctamente. Escriba un trabajo por lotes que se ejecute a medianoche al final del período (mes / semana / día) para hacer esto.
fuente
El saldo es una cantidad calculada basada en ciertas reglas comerciales, por lo que sí, no desea mantener el saldo sino calcularlo a partir de las transacciones en la tarjeta y, por lo tanto, de la cuenta.
Desea realizar un seguimiento de todas las transacciones en la tarjeta para auditoría e informes de estado de cuenta, e incluso datos de diferentes sistemas más adelante.
En pocas palabras: calcule cualquier valor que deba calcularse cuando lo necesite
fuente