Nous développons une plate-forme pour les cartes prépayées, qui contient essentiellement des données sur les cartes et leur solde, les paiements, etc.
Jusqu'à présent, nous avions une entité de carte qui a une collection d'entités de compte, et chaque compte a un montant, qui est mis à jour dans chaque dépôt / retrait.
Il y a maintenant un débat dans l'équipe; quelqu'un nous a dit que cela enfreint les 12 règles de Codd et que la mise à jour de sa valeur à chaque paiement est un problème.
Est-ce vraiment un problème?
Si tel est le cas, comment pouvons-nous résoudre ce problème?
database-design
rdbms
Mithir
la source
la source
Réponses:
Oui, ce n'est pas normalisé, mais parfois les conceptions non normalisées l'emportent pour des raisons de performances.
Cependant, je l'aborderais probablement un peu différemment, pour des raisons de sécurité. (Avertissement: je ne travaille pas actuellement, et je n'ai jamais travaillé dans le secteur financier.
Ayez une table pour les soldes affichés sur les cartes. Cela aurait une ligne insérée pour chaque compte, indiquant le solde affiché à la fin de chaque période (jour, semaine, mois ou tout ce qui est approprié). Indexez ce tableau par numéro de compte et date.
Utilisez une autre table pour conserver les transactions en attente, qui sont insérées à la volée. À la fin de chaque période, exécutez une routine qui ajoute les transactions non reportées au dernier solde de clôture du compte pour calculer le nouveau solde. Soit marquer les transactions en attente comme validées, soit regarder les dates pour déterminer ce qui est encore en attente.
De cette façon, vous avez un moyen de calculer un solde de carte à la demande, sans avoir à résumer tout l'historique du compte, et en plaçant le recalcul du solde dans une routine de validation dédiée, vous pouvez vous assurer que la sécurité des transactions de ce recalcul est limitée à un seul endroit (et également limiter la sécurité sur la table du solde afin que seule la routine de comptabilisation puisse y écrire).
Ensuite, conservez autant de données historiques que l'exigent l'audit, le service client et les exigences de performance.
la source
De l'autre côté, il y a un problème que nous rencontrons fréquemment dans les logiciels de comptabilité. Paraphrasé:
La réponse est bien sûr non. Il y a quelques approches ici. L'un stocke la valeur calculée. Je ne recommande pas cette approche car les bogues logiciels qui provoquent des valeurs incorrectes sont très difficiles à détecter et j'éviterais donc cette approche.
Une meilleure façon de le faire est ce que j'appelle l'approche log-snapshot -greg. Dans cette approche, nos paiements et utilisations sont des insertions et nous ne mettons jamais à jour ces valeurs. Périodiquement, nous agrégons les données sur une période de temps et insérons un enregistrement d'instantané calculé qui représente les données au moment où l'instantané est devenu valide (généralement une période de temps avant la date actuelle).
Maintenant, cela ne viole pas les règles de Codd car au fil du temps, les instantanés peuvent être moins que parfaitement dépendants des données de paiement / d'utilisation insérées. Si nous avons des instantanés de travail, nous pouvons décider de purger des données vieilles de 10 ans sans affecter notre capacité à calculer les soldes actuels à la demande.
la source
Pour des raisons de performances, dans la plupart des cas, nous devons stocker le solde actuel - sinon, le calculer à la volée peut éventuellement devenir excessivement lent.
Nous stockons les totaux cumulés précalculés dans notre système. Pour garantir que les nombres sont toujours corrects, nous utilisons des contraintes. La solution suivante a été copiée depuis mon blog. Il décrit un inventaire, qui est essentiellement le même problème:
Le calcul des totaux cumulés est notoirement lent, que vous le fassiez avec un curseur ou avec une jointure triangulaire. Il est très tentant de dénormaliser, de stocker les totaux en cours dans une colonne, surtout si vous la sélectionnez fréquemment. Cependant, comme d'habitude lorsque vous dénormalisez, vous devez garantir l'intégrité de vos données dénormalisées. Heureusement, vous pouvez garantir l'intégrité des totaux cumulés avec des contraintes - tant que toutes vos contraintes sont fiables, tous vos totaux cumulés sont corrects. De cette façon, vous pouvez facilement vous assurer que le solde actuel (totaux cumulés) n'est jamais négatif - l'application par d'autres méthodes peut également être très lente. Le script suivant illustre la technique.
la source
C'est une très bonne question.
En supposant que vous ayez une table de transactions qui stocke chaque débit / crédit, il n'y a rien de mal avec votre conception. En fait, j'ai travaillé avec des systèmes de télécommunications prépayés qui fonctionnaient exactement de cette façon.
La principale chose que vous devez faire est de vous assurer que vous effectuez
SELECT ... FOR UPDATE
le solde pendant que vous effectuezINSERT
le débit / crédit. Cela garantira le bon équilibre en cas de problème (car toute la transaction sera annulée).Comme d'autres l'ont fait remarquer, vous aurez besoin d'un instantané des soldes à des périodes spécifiques pour vérifier que toutes les transactions d'une somme donnée avec les soldes de début / fin de période sont correctes. Pour ce faire, écrivez un travail par lots qui s'exécute à minuit à la fin de la période (mois / semaine / jour).
la source
Le solde est un montant calculé en fonction de certaines règles commerciales, donc oui, vous ne voulez pas garder le solde mais plutôt le calculer à partir des transactions sur la carte et donc du compte.
Vous souhaitez garder une trace de toutes les transactions sur la carte pour l'audit et le rapport de déclaration, et même les données de différents systèmes plus tard.
Conclusion - calculez toutes les valeurs qui doivent être calculées au fur et à mesure que vous en avez besoin
la source