Мы разрабатываем платформу для карт предоплаты, которая в основном содержит данные о картах и их балансе, платежах и т. Д.
До сих пор у нас была сущность Карточка, которая имеет набор сущностей Счета, и у каждой Счета есть Сумма, которая обновляется при каждом пополнении / снятии.
Сейчас в команде идут дебаты; кто-то сказал нам, что это нарушает 12 правил Кодда и что обновление его стоимости при каждом платеже является проблемой.
Это действительно проблема?
Если это так, как мы можем это исправить?
database-design
rdbms
Mithir
источник
источник
Ответы:
Да, это ненормализовано, но иногда ненормализованные проекты выигрывают по причинам производительности.
Тем не менее, я бы, вероятно, подошел к этому немного по-другому из соображений безопасности. (Отказ от ответственности: в настоящее время я не работаю в финансовом секторе и никогда не работал).
Есть таблица для размещенных остатков на карточках. Для каждой учетной записи будет вставлена строка с указанием проведенного баланса на конец каждого периода (день, неделя, месяц или что-либо более подходящее). Индексируйте эту таблицу по номеру счета и дате.
Используйте другую таблицу для хранения ожидающих транзакций, которые вставляются на лету. В конце каждого периода запустите процедуру, которая добавляет неопубликованные транзакции к последнему сальдо закрытия счета для расчета нового сальдо. Либо пометьте ожидающие транзакции как опубликованные, либо посмотрите на даты, чтобы определить, что еще ожидает рассмотрения.
Таким образом, у вас есть средство для расчета баланса карты по требованию, без необходимости суммировать всю историю счета, и, поместив перерасчет баланса в специальную процедуру разноски, вы можете гарантировать, что безопасность транзакций этого перерасчета ограничена одно место (а также ограничить безопасность таблицы баланса, чтобы в нее могли писать только процедуры проводки).
Затем просто сохраняйте столько исторических данных, сколько необходимо для аудита, обслуживания клиентов и требований к производительности.
источник
С другой стороны, есть проблема, с которой мы часто сталкиваемся в бухгалтерском программном обеспечении. Перефразировано:
Ответ, конечно, нет, вы не делаете. Здесь есть несколько подходов. Один хранит рассчитанное значение. Я не рекомендую этот подход, потому что программные ошибки, которые приводят к неправильным значениям, очень трудно отследить, и поэтому я бы избегал этого подхода
Лучший способ сделать это - то, что я называю подходом log-snapshot-aggregate. При таком подходе наши платежи и использование являются вставками, и мы никогда не обновляем эти значения. Периодически мы агрегируем данные за определенный период времени и вставляем вычисленную запись моментального снимка, которая представляет данные в момент, когда моментальный снимок стал действительным (обычно за период до его появления ).
Теперь это не нарушает правила Кодда, потому что со временем моментальные снимки могут не полностью зависеть от введенных данных об оплате / использовании. Если у нас есть рабочие снимки, мы можем решить очистить данные за 10 лет, не влияя на нашу способность вычислять текущие остатки по требованию.
источник
Из соображений производительности в большинстве случаев мы должны хранить текущий баланс - в противном случае его вычисление на лету может в конечном итоге стать чрезмерно медленным.
Мы храним предварительно рассчитанные промежуточные итоги в нашей системе. Чтобы гарантировать, что числа всегда правильные, мы используем ограничения. Следующее решение было скопировано из моего блога. Он описывает инвентарь, который по сути та же проблема:
Вычисление промежуточных итогов печально известно медленно, независимо от того, делаете ли вы это с помощью курсора или треугольного соединения. Очень заманчиво денормализовать, хранить промежуточные итоги в столбце, особенно если вы часто его выбираете. Однако, как обычно, когда вы денормализуете, вы должны гарантировать целостность ваших денормализованных данных. К счастью, вы можете гарантировать целостность промежуточных итогов с ограничениями - если все ваши ограничения являются доверенными, все промежуточные итоги верны. Таким образом, вы также можете легко гарантировать, что текущий баланс (промежуточные итоги) никогда не будет отрицательным - применение других методов также может быть очень медленным. Следующий скрипт демонстрирует технику.
источник
Это очень хороший вопрос.
Предполагая, что у вас есть таблица транзакций, в которой хранятся все дебеты / кредиты, в вашем дизайне нет ничего плохого. Фактически, я работал с предоплаченными телекоммуникационными системами, которые работали именно таким образом.
Главное, что вам нужно сделать, это убедиться, что вы делаете
SELECT ... FOR UPDATE
баланс, пока выINSERT
дебет / кредит. Это будет гарантировать правильный баланс, если что-то пойдет не так (потому что вся транзакция будет откатана).Как уже отмечали другие, вам потребуется снимок сальдо за определенные периоды времени, чтобы убедиться, что все транзакции в данном периоде суммируются с правильными значениями начального / конечного сальдо периода. Для этого напишите пакетное задание, которое выполняется в полночь в конце периода (месяц / неделя / день).
источник
Баланс представляет собой вычисленную сумму, основанную на определенных бизнес-правилах, поэтому да, вы не хотите сохранять баланс, а скорее рассчитываете его из транзакций по карте и, следовательно, по счету.
Вы хотите отслеживать все транзакции на карте для аудита и отчетности, а также даже данные из других систем в дальнейшем.
Итог - вычисление любых значений, которые должны быть вычислены, как и когда вам нужно
источник