Projektując duże relacyjne bazy danych często podejmujemy decyzję o odejściu od normalnej postaci, czyli denormalizacji.
Przyczyny tego mogą być różne, takie jak próba przyspieszenia dostępu do określonych danych, ograniczenia używanej platformy/struktury/narzędzi programistycznych oraz brak umiejętności programisty/projektanta bazy danych.
Ściśle mówiąc, odniesienie do ograniczeń ramowych itp. jest w rzeczywistości próbą uzasadnienia braku umiejętności.
Zdenormalizowane dane to luka, dzięki której łatwo jest doprowadzić naszą bazę danych do niespójnego (nieintegralnego) stanu.
Co możemy z tym zrobić?
Przykład
W bazie danych znajduje się tabela z niektórymi operacjami finansowymi:przyjmowaniem i wydawaniem środków na różnych rachunkach.
Zawsze musimy znać saldo konta.
W danych znormalizowanych saldo funduszu jest zawsze wartością obliczoną. Zamierzamy obliczyć sumę wpływów bez obciążania rachunku.
Jednak obliczanie salda za każdym razem, gdy jest wiele operacji, jest zbyt kosztowne. Dlatego zdecydowano się przechowywać rzeczywiste saldo w osobnej tabeli. Jak aktualizujemy dane w tej tabeli?
Rozwiązanie jest „jak zwykle”
Niemal we wszystkich systemach informatycznych, z którymi miałem do czynienia, zadanie to wykonywała aplikacja zewnętrzna, która implementowała logikę biznesową. Masz szczęście, jeśli aplikacja jest prosta i istnieje tylko jeden punkt zmiany danych, z formularza w interfejsie użytkownika. Co jednak, jeśli istnieją pewne importy, interfejsy API, aplikacje innych firm itp. wykonywane przez różne osoby i zespoły? Co się stanie, jeśli istnieje kilka tabel z sumami zamiast jednej? Co się stanie, jeśli istnieje więcej niż jedna tabela z operacjami?
Coraz trudniej jest monitorować, czy programista zaktualizował kilka tabel podczas aktualizacji operacji. Dane tracą integralność. Saldo konta nie odpowiada operacjom. Oczywiście testy muszą ujawnić takie sytuacje. Jednak nasz świat nie jest idealny.
Wyzwalacze
Alternatywnie, wyzwalacze są używane do kontrolowania integralności zdenormalizowanych danych.
Słyszałem, że wyzwalacze znacznie spowalniają bazę danych, więc używanie ich nie ma sensu.
Drugim argumentem było to, że cała logika znajduje się w osobnej aplikacji i utrzymywanie logiki biznesowej w różnych miejscach jest nieuzasadnione.
Zastanówmy się.
Opóźnienia
Wewnątrz transakcji uruchamiany jest wyzwalacz, który modyfikuje dane w tabeli. Transakcja nie może zostać zakończona, dopóki wyzwalacz nie wykona wymaganych kroków. Dlatego wniosek jest taki, że wyzwalacze muszą być „lekkie”.
Przykład „ciężkiego” zapytania w wyzwalaczu jest następujący:
update totals set total = select sum(operations.amount) from operations where operations.account = current_account where totals.account = current_account
Zapytanie odnosi się do tabeli z operacjami i podsumowuje całkowitą kwotę operacji dla konta .
Wraz ze wzrostem bazy danych takie zapytanie będzie pochłaniało coraz więcej czasu i zasobów. Ten sam wynik możemy jednak otrzymać za pomocą lekkiego zapytania następującego typu:
update totals set total = totals.total + current_amount where totals.account = current_account
Podczas dodawania nowego wiersza ten wyzwalacz po prostu zwiększy sumę na koncie bez jej obliczania. Suma nie zależy od ilości danych w tabelach. Ponowne obliczanie sumy nie ma sensu, ponieważ możemy być pewni, że wyzwalacz uruchamia się za każdym razem podczas dodawania nowej operacji.
Usuwanie lub modyfikowanie wierszy odbywa się w ten sam sposób. Wyzwalacze tego typu nie spowalniają operacji, jednak zapewniają sprzężenie danych i integralność.
Za każdym razem, gdy doświadczałem „lagów” podczas dodawania danych do tabeli z wyzwalaczem, był to przykład takiego „ciężkiego” zapytania. W większości przypadków możliwe było przepisanie go w „łatwym” zapytaniu.
Logika biznesowa
Musimy odróżnić funkcje zapewniające integralność danych od logiki biznesowej. W każdym przypadku zadaję pytanie, czy gdyby dane były znormalizowane, czy potrzebna byłaby taka funkcja? Jeśli jest pozytywna, funkcja jest logiką biznesową. Jeśli jest ujemna, funkcja ma zapewnić integralność danych. Możesz opakować te funkcje w wyzwalacze.
Istnieje jednak opinia, że łatwo jest zaimplementować całą logikę biznesową za pomocą DBMS, takich jak PostgreSQL lub Oracle.
Mam nadzieję, że ten artykuł pomoże zmniejszyć liczbę błędów w Twoim systemie informacyjnym.
Oczywiście daleko mi do myślenia, że wszystko, co tu napisano, jest ostateczną prawdą. W prawdziwym życiu wszystko jest oczywiście znacznie bardziej skomplikowane. Dlatego musisz podjąć decyzję w każdym konkretnym przypadku. Wykorzystaj swoje myślenie inżynierskie!
PS
- W artykule zwróciłem uwagę na jedyny aspekt używania wyzwalaczy jako potężnego narzędzia.
- Podejście opisane w artykule pozwala uniknąć indeksów w Operacjach tabeli, co z kolei może przyspieszyć proces dodawania danych do tej tabeli. Przy dużych ilościach takie podejście łatwo kompensuje czas spędzony na spuście.
- Ważne jest, aby zrozumieć, jakich narzędzi potrzebujemy. W takim przypadku unikniesz wielu problemów.