Opracowujemy platformę dla kart przedpłaconych, która zasadniczo przechowuje dane o kartach i ich saldzie, płatnościach itp.
Do tej pory istniała jednostka Karty, która ma kolekcję Konta, a każde Konto ma Kwotę, która aktualizuje się przy każdym Depozycie / Wypłatie.
W zespole toczy się teraz debata; ktoś powiedział nam, że łamie to 12 zasad Codda i że aktualizowanie jego wartości przy każdej płatności jest kłopotliwe.
Czy to naprawdę problem?
Jeśli tak, to jak możemy to naprawić?
database-design
rdbms
Mithir
źródło
źródło
Odpowiedzi:
Tak, to nienormalizowane, ale czasami nienormalizowane projekty wygrywają ze względu na wydajność.
Prawdopodobnie jednak podchodziłbym do tego trochę inaczej ze względów bezpieczeństwa. (Oświadczenie: Obecnie nie pracuję ani nigdy nie pracowałem w sektorze finansowym. Po prostu to wyrzucam.)
Przygotuj tabelę dla zaksięgowanych sald na kartach. Oznaczałoby to wstawienie wiersza dla każdego konta, wskazującego zaksięgowane saldo na koniec każdego okresu (dzień, tydzień, miesiąc lub cokolwiek jest właściwe). Indeksuj tę tabelę według numeru konta i daty.
Użyj innej tabeli do przechowywania oczekujących transakcji, które są wstawiane na bieżąco. Na koniec każdego okresu uruchom procedurę dodającą nieopublikowane transakcje do ostatniego salda zamknięcia rachunku, aby obliczyć nowe saldo. Oznacz oczekujące transakcje jako zaksięgowane lub sprawdź daty, aby ustalić, co jest nadal w toku.
W ten sposób masz możliwość obliczenia salda karty na żądanie, bez konieczności sumowania całej historii rachunku, a umieszczając ponowne obliczanie salda w specjalnej procedurze księgowania, możesz zapewnić, że bezpieczeństwo transakcji tego ponownego obliczenia jest ograniczone do jedno miejsce (a także ograniczyć bezpieczeństwo na stole bilansowym, aby tylko procedura księgowania mogła do niego pisać).
Następnie przechowuj tyle danych historycznych, ile jest to wymagane przez audyt, obsługę klienta i wymagania dotyczące wydajności.
źródło
Z drugiej strony jest problem, z którym często spotykamy się w oprogramowaniu księgowym. Parafrazowane:
Oczywiście odpowiedź brzmi „nie”. Jest tu kilka podejść. Jednym z nich jest zapisanie obliczonej wartości. Nie polecam tego podejścia, ponieważ błędy oprogramowania, które powodują nieprawidłowe wartości, są bardzo trudne do wyśledzenia, dlatego unikałbym tego.
Lepszym sposobem na to jest to, co nazywam podejściem log-snapshot-agregate. W tym podejściu nasze płatności i zastosowania są wstawkami i nigdy nie aktualizujemy tych wartości. Okresowo agregujemy dane w określonym przedziale czasu i wstawiamy obliczony rekord migawki, który reprezentuje dane w momencie, gdy migawka stała się ważna (zwykle okres czasu przed obecnym).
Teraz nie łamie to zasad Codda, ponieważ z czasem migawki mogą być mniej niż idealnie zależne od wstawionych danych dotyczących płatności / użytkowania. Jeśli mamy działające migawki, możemy zdecydować się na usunięcie 10-letnich danych bez wpływu na naszą zdolność do obliczania bieżących sald na żądanie.
źródło
Ze względów wydajnościowych w większości przypadków musimy przechowywać bieżące saldo - w przeciwnym razie obliczanie go w locie może ostatecznie stać się zbyt wolne.
W naszym systemie przechowujemy wstępnie obliczone sumy bieżące. Aby zagwarantować, że liczby są zawsze poprawne, stosujemy ograniczenia. Poniższe rozwiązanie zostało skopiowane z mojego bloga. Opisuje inwentarz, który jest zasadniczo tym samym problemem:
Obliczanie sum całkowitych jest notorycznie wolne, niezależnie od tego, czy robisz to za pomocą kursora, czy za pomocą połączenia trójkątnego. Denormalizacja jest bardzo kusząca, aby przechowywać bieżące sumy w kolumnie, szczególnie jeśli często ją wybierasz. Jednak, jak zwykle podczas denormalizacji, należy zagwarantować integralność zdormalizowanych danych. Na szczęście możesz zagwarantować integralność działających sum z ograniczeniami - dopóki wszystkie ograniczenia są zaufane, wszystkie działające sumy są poprawne. W ten sposób możesz łatwo upewnić się, że bieżące saldo (sumy bieżące) nigdy nie jest ujemne - egzekwowanie innymi metodami może być również bardzo wolne. Poniższy skrypt demonstruje technikę.
źródło
To jest bardzo dobre pytanie.
Zakładając, że masz tabelę transakcji, która przechowuje każde polecenie zapłaty / kredyt, nie ma nic złego w twoim projekcie. W rzeczywistości pracowałem z przedpłaconymi systemami telekomunikacyjnymi, które działały dokładnie w ten sposób.
Najważniejsze, co musisz zrobić, to upewnić się, że robisz
SELECT ... FOR UPDATE
saldo podczasINSERT
debetu / kredytu. Zapewni to prawidłowe saldo, jeśli coś pójdzie nie tak (ponieważ cała transakcja zostanie wycofana).Jak zauważyli inni, będziesz potrzebować migawki sald w określonych przedziałach czasu, aby sprawdzić, czy wszystkie transakcje w danym okresie sumują się z saldami początku / końca okresu. Napisz zadanie wsadowe, które będzie uruchamiane o północy pod koniec okresu (miesiąc / tydzień / dzień), aby to zrobić.
źródło
Saldo jest obliczoną kwotą opartą na pewnych zasadach biznesowych, więc tak, nie chcesz zachować salda, a raczej obliczyć go z transakcji na karcie, a zatem rachunku.
Chcesz śledzić wszystkie transakcje na karcie do celów audytu i raportowania wyciągów, a nawet później danych z różnych systemów.
Konkluzja - oblicz wszystkie wartości, które należy obliczyć w dowolnym momencie
źródło