Czy powinienem zdefiniować relacje między tabelami w bazie danych, czy tylko w kodzie?

60

Z mojego doświadczenia wynika, że ​​wiele projektów, które przeczytałem w przeszłości, nie zawierało definicji relacji w bazie danych, a jedynie zdefiniowało je w kodzie źródłowym. Zastanawiam się więc, jakie są zalety / wady definiowania relacji między tabelami w bazie danych i kodzie źródłowym? A szersze pytanie dotyczy innych zaawansowanych funkcji współczesnych baz danych, takich jak kaskada, wyzwalacze, procedury ... W moich myślach są pewne kwestie:

W bazie danych:

  • Prawidłowe dane z projektu. Zapobiegaj błędom aplikacji, które mogą powodować nieprawidłowe dane.

  • Ogranicz liczbę podróży w obie strony do aplikacji podczas wstawiania / aktualizowania danych, ponieważ aplikacja musi wykonać więcej zapytań, aby sprawdzić integralność danych.

W kodzie źródłowym:

  • Bardziej elastyczne.

  • Lepsze przy skalowaniu do wielu baz danych, ponieważ czasami relacja może być między bazami danych.

  • Większa kontrola nad integralnością danych. Baza danych nie musi sprawdzać za każdym razem, gdy aplikacja modyfikuje dane (złożoność może wynosić O (n) lub O (n log n) (?)). Zamiast tego jest delegowany do aplikacji. I myślę, że obsługa integralności danych w aplikacji spowoduje więcej pełnych komunikatów o błędach niż korzystanie z bazy danych. Np .: kiedy tworzysz serwer API, jeśli zdefiniujesz relacje w bazie danych i coś pójdzie nie tak (np. Encja, do której istnieje odwołanie, nie istnieje), otrzymasz wyjątek SQL z komunikatem. Prostym sposobem będzie zwrócenie klientowi 500, że występuje „Wewnętrzny błąd serwera” i klient nie będzie miał pojęcia, co się dzieje. Lub serwer może przeanalizować komunikat, aby dowiedzieć się, co jest nie tak, co moim zdaniem jest brzydkie i podatne na błędy. Jeśli pozwolisz aplikacji to obsłużyć,

Czy jest coś jeszcze?

Edycja: jak wskazuje Kilian, moje zdanie na temat wydajności i integralności danych jest bardzo mylne. Zedytowałem więc, żeby poprawić mój punkt. Całkowicie rozumiem, że pozwolenie na obsługę bazy danych będzie bardziej wydajnym i niezawodnym podejściem. Sprawdź zaktualizowane pytanie i podziel się z nim przemyśleniami.

Edycja: dziękuję wszystkim. Odpowiedzi, które otrzymałem, wskazują, że ograniczenia / relacje powinny być zdefiniowane w bazie danych. :) Mam jeszcze jedno pytanie, ponieważ jest ono całkowicie poza zakresem tego pytania, właśnie opublikowałem je jako osobne pytanie: Obsługa błędu bazy danych dla serwera API . Proszę zostawić pewne spostrzeżenia.

Yoshi
źródło
4
„ponieważ aplikacja musi wykonać więcej zapytań, aby sprawdzić integralność danych”. Niekoniecznie. Jeśli baza danych znajduje się w pełni pod kontrolą aplikacji, dodatkowe kontrole integralności danych mogą być nadmiernie defensywnym programowaniem. Nie musisz ich koniecznie; po prostu odpowiednio przetestuj aplikację, aby upewnić się, że wprowadza tylko prawidłowe zmiany w bazie danych.
9
Jest jedna rzecz, o której nigdy nie należy zapominać: chyba że wszyscy zaangażowani napisają doskonałe oprogramowanie, jeśli kontrole znajdują się w oprogramowaniu, jedna z tych kontroli zakończy się niepowodzeniem i doprowadzi do braku egzekwowania ograniczeń. Nie chodzi o to, czy, ale kiedy. Prowadzi to do trudnych do odtworzenia błędów i długich godzin masowania danych w celu ponownego dopasowania do wymuszonych przez oprogramowanie ograniczeń.
Dabu
10
Coś, o czym warto wspomnieć ... po wprowadzeniu problemów z integralnością do swojej bazy danych jest krewny do otwarcia skrzynki Pandory. Koszmarem jest przywrócenie integralności anomalii opartej na anomalii. Utrzymywanie ścisłej kontroli nad bazą danych może być kłopotliwe, ale na dłuższą metę zaoszczędzi ci wiele bólu.
DanK
3
W kodzie źródłowym: w końcu piszesz większość bazy danych.
Blrfl,
7
Kiedyś zadałem bardzo utalentowanemu programistowi podobne pytanie, które powiedział mi: „To jak hamowanie w samochodzie. Nie chodzi o to, aby samochód jechał wolniej, ale by mógł jechać bezpieczniej”. Pewnie można go uruchomić bez ograniczeń, ale jeśli w jakiś sposób dostaną się złe dane, może to spowodować poważną awarię
mercurial

Odpowiedzi:

70

TL; DR: Ograniczenia relacji powinny iść do bazy danych.


Twoja aplikacja nie jest wystarczająco duża.

Masz rację, że wymuszanie relacji między bazami danych może wymagać egzekwowania ich w aplikacji.

Chciałbym jednak zwrócić uwagę, że najpierw powinieneś sprawdzić dokumentację używanego oprogramowania bazy danych i sprawdzić istniejące oferty produktów. Na przykład, są Postgres i MySQL.

I nawet jeśli skończy się na tym, że musisz mieć jakieś potwierdzenie w aplikacji, nie wylewaj dziecka z kąpielą . W końcu im mniej musisz zrobić, tym lepiej.

Wreszcie, jeśli martwisz się o przyszłe problemy ze skalowalnością, obawiam się, że twoja aplikacja będzie musiała przejść znaczące zmiany, zanim będzie mogła się skalować. Zasadniczo za każdym razem, gdy powiększysz 10-krotnie, musisz przeprojektować ... więc nie zatapiajmy zbyt dużych pieniędzy w nieumiejętność przewidywania problemów ze skalowalnością, a zamiast tego używaj pieniędzy, aby faktycznie dotrzeć do punktu, w którym masz te problemy.

Twoja aplikacja nie jest wystarczająco poprawna.

Jaka jest szansa, że ​​używana baza danych ma wadliwą implementację czeku, w porównaniu z szansą, że twoja aplikacja ma wadliwą implementację czeku?

A który z nich zmieniasz najczęściej?

Założę się, że baza danych jest poprawna w dowolnym momencie .

Twoi programiści nie myślą wystarczająco dobrze.

Zmniejsz liczbę podróży w obie strony do aplikacji podczas wstawiania / aktualizowania danych, ponieważ aplikacja musi wykonać więcej zapytań, aby sprawdzić integralność danych.

Czerwona flaga ! 1

Jeśli myślisz:

  • sprawdź, czy rekord istnieje
  • jeśli nie, wstaw rekord

wtedy nie powiodła się najbardziej podstawowa kwestia współbieżności: inny proces / wątek mógł dodawać rekord podczas pracy.

Jeśli myślisz:

  • sprawdź, czy rekord istnieje
  • jeśli nie, wstaw rekord
  • sprawdź, czy rekord został wstawiony jako duplikat

wtedy nie udało Ci się rozliczyć MVCC: widok posiadanej bazy danych jest migawką w momencie rozpoczęcia transakcji; to jednak nie pokazać wszystkie aktualizacje, które mają miejsce, a może nawet nie popełnione.

Utrzymywanie ograniczeń w wielu sesjach jest naprawdę trudnym problemem, ciesz się, że zostało rozwiązane w bazie danych.

1 Chyba że baza danych poprawnie implementuje właściwość Serializable; ale niewielu tak.


Ostatni, ubiegły, zeszły:

I myślę, że obsługa integralności danych w aplikacji pozwoli na bardziej szczegółowy komunikat o błędzie niż przy użyciu bazy danych. Np .: podczas tworzenia serwera API. Jeśli zdefiniujesz relacje w bazie danych i coś pójdzie nie tak (np. Istnienie, do którego istnieje odwołanie, nie istnieje), otrzymasz wyjątek SQL z komunikatem.

Nie analizuj komunikatów o błędach , jeśli używasz bazy danych klasy produkcyjnej, powinna zwracać błędy strukturalne. Będziesz mieć przynajmniej kod błędu, aby wskazać, co może być nie tak, i na podstawie tego kodu możesz stworzyć odpowiedni komunikat o błędzie.

Zauważ, że w większości przypadków wystarczy kod: jeśli masz kod błędu informujący, że klucz obcy, do którego istnieje odwołanie, nie istnieje, oznacza to, że ta tabela ma tylko jeden klucz obcy, więc wiesz w kodzie, na czym polega problem .

I, bądźmy szczerzy tutaj, przez większość czasu i tak nie będziesz w stanie z wdziękiem obsługiwać błędów. Tylko dlatego, że jest ich tak wiele, że nie zdołasz uwzględnić ich wszystkich ...

... który tylko wiąże się z punktem poprawności powyżej. Za każdym razem, gdy pojawia się komunikat „500: Wewnętrzny błąd serwera”, ponieważ uruchomiono ograniczenie bazy danych i nie zostało ono obsłużone, oznacza to, że baza danych Cię uratowała, ponieważ zapomniałeś obsługiwać ją w kodzie.

Matthieu M.
źródło
3
Haha, napisałeś to tak, jak pisałem swój komentarz, ironicznie podkreślając kwestię, którą oboje zajmujemy. Całkowicie się zgadzam: nie można nawet robić integralności ani ograniczeń w kodzie innym niż DB. Transakcje nie widzą wyników innych, dopóki nie zostaną popełnione (a nawet wtedy może nie). Możesz mieć złudzenie uczciwości, ale może to powodować problemy z synchronizacją lub poważnymi problemami skalowalności z powodu blokad. Tylko baza danych może to zrobić poprawnie.
LoztInSpace
8
Wszystkie dobre punkty. Innym jest to, że relacje w bazie danych są samok dokumentujące. Jeśli kiedykolwiek musiałeś dokonać inżynierii wstecznej bazy danych, której relacje zdefiniowano tylko w zapytaniu do kodu, nienawidzisz każdego, kto to robi.
Kat
1
@ Kat11: To prawda. A samoopisanie ma również tę zaletę, że narzędzia mogą łatwo zrozumieć dane i działać na nich, co czasem może być przydatne.
Matthieu M.,
1
Twój argument na temat MVCC jest niedokładny w bazach danych, które poprawnie implementują izolację SERIALIZABLE (na przykład, robią to nowoczesne wersje PostgreSQL - chociaż wiele głównych RDBMS tego nie robi). W takim DB nawet pierwsze naiwne podejście działałoby poprawnie - jeśli zapisuje konflikt, zostaną one wycofane jako błąd serializacji.
James_pic
1
W bazach danych, które poprawnie wdrażają SERIALIZABLE, jeśli weźmiesz wszystkie pomyślnie zatwierdzone transakcje, wówczas istnieje pewne uporządkowanie (które może nie być takie samo jak zamówienie z zegarem ściennym), tak że jeśli uruchomiłeś je wszystkie szeregowo (bez współbieżności) w tej kolejności wszystkie wyniki byłyby dokładnie takie same. Trudno jest to zrobić poprawnie, a specyfikacje SQL są na tyle niejasne, że można przekonać się, że zezwolenie na zapisywanie pochylenia na poziomie SERIALIZABLE jest w porządku, więc wielu dostawców DB traktuje SERIALIZABLE jako SNAPSHOT ISOLATION (patrzę na ciebie Oracle).
James_pic
119

Baza danych nie musi sprawdzać integralności danych za każdym razem, gdy aplikacja modyfikuje dane.

To głęboko błędny punkt. Właśnie w tym celu stworzono bazy danych. Jeśli potrzebujesz sprawdzania integralności danych (i jeśli uważasz, że ich nie potrzebujesz, prawdopodobnie się mylisz), to pozwolenie na obsługę danych przez bazę danych jest prawie na pewno bardziej wydajne i mniej podatne na błędy niż robienie tego w logice aplikacji.

Kilian Foth
źródło
5
@ dan1111 Nie rozumiem twojego komentarza ... czy mówisz: proste ograniczenia są egzekwowane przez bazę danych, więc nie stanowią one problemu dla kodu aplikacji, bardziej złożone ograniczenia są zbyt trudne do wdrożenia, więc po prostu zrezygnuj z nich? A może mówisz, że wdrażanie złożonych ograniczeń za pomocą wyzwalaczy bazy danych (i podobnego mechanizmu) jest zbyt złożone i dlatego lepiej je zaimplementować w kodzie aplikacji?
Bakuriu
47
Nie można nawet robić integralności ani ograniczeń w kodzie innym niż DB. Transakcje nie widzą wyników innych, dopóki nie zostaną popełnione (a nawet wtedy może nie). Możesz mieć złudzenie uczciwości, ale może to powodować problemy z synchronizacją lub poważnymi problemami skalowalności z powodu blokad. Tylko baza danych może to zrobić poprawnie.
LoztInSpace
17
Anegdotycznie, aby podążać za komentarzem @ LoztInSpace, kiedyś pracowałem dla (strasznej) firmy, w której jedna z tych tabel została skonfigurowana w taki sposób, że zamiast pozwalać DB automatycznie zwiększać identyfikator, aplikacja pobierała identyfikator ostatniego wiersza, dodał jeden do niego i użył go jako nowego identyfikatora. Niestety, mniej więcej raz w tygodniu wstawiane są duplikaty identyfikatorów, co powoduje zawieszenie aplikacji.
Trotski94,
9
@ dan1111 Nigdy nie piszesz błędów w aplikacji, prawda?
user253751,
4
@DavidPacker Mogę się zgodzić, jednak gdy masz wielu klientów uzyskujących dostęp do bazy danych, możesz wymusić ograniczenia tylko w bazie danych. Chyba, że ​​zaczniesz blokować tabele hurtowo zamiast rzędami, z osiągniętym spadkiem wydajności.
Iker
51

Ograniczenia powinny leżeć w bazie danych, ponieważ (przy najlepszej woli na świecie) twoja aplikacja nie będzie jedyną rzeczą, aby kiedykolwiek uzyskać dostęp do tej bazy danych.

W pewnym momencie może zaistnieć potrzeba skryptu w bazie danych lub migracja danych z jednej tabeli do drugiej podczas wdrażania.

Dodatkowo możesz spełnić inne wymagania, np. „Duży klient X naprawdę potrzebuje tego arkusza Excela importowanego do naszej bazy danych aplikacji po południu”, w którym nie będziesz miał luksusu, dostosowując kod aplikacji, aby pasował do sytuacji, gdy zrobi to brudny skrypt SQL w samą porę.

To tutaj integralność na poziomie bazy danych uratuje twój bekon.


Dodatkowo, wyobraź sobie programistę, który po odejściu przejmuje Twoją rolę w tej firmie, a następnie ma za zadanie wprowadzić zmiany w bazie danych.

Czy będzie cię nienawidził, jeśli w bazie danych nie ma żadnych ograniczeń FK, aby mógł powiedzieć, jakie relacje ma tabela przed jej zmianą? ( Wskazówka, odpowiedź brzmi tak )

Paddy
źródło
33
Bracie Nie mogę powiedzieć, ile razy musiałem tłumaczyć ludziom, że baza danych ma więcej niż jednego klienta! Nawet jeśli w tej chwili istnieje tylko jeden klient i tylko jedna droga do wejścia danych do systemu, zaprojektowanie aplikacji i schematu w oparciu o to założenie jest najlepszym sposobem, by Future Yoshi nienawidził przeszłości Yoshi.
Greg Burghardt
9
@nikonyrh Nie zrobiłbym tego. Istnieją ograniczenia, dzięki którym aplikacje mogą polegać na spójnych danych. Wyłączenie FK „tylko po to, żeby się dostać” to szaleństwo.
Paddy
5
Zgoda. Ponadto, nawet jeśli twoja aplikacja jest jedynym klientem, możesz mieć różne wersje aplikacji próbujące wymusić nieco inne ograniczenia. Zwykle pojawia się wesołość (cóż, niezupełnie. Bardziej przypomina „chaos i całkowitą frustrację” niż „wesołość”).
Iker
5
Mogę absolutnie to potwierdzić. W moim przypadku utknąłem na MyISAM, który tak naprawdę nie obsługuje kluczy obcych, więc otrzymałem 250 GB danych z integralnością wymuszoną przez aplikację. Kiedy zaczęło się przycinanie danych, aby zaległości osiągnęły łatwiejszy do zarządzania rozmiar, a kiedy stało się jasne, że sama aplikacja nie będzie w stanie poradzić sobie z tym, powstał chaos. Nie wiem, dlaczego używam czasu przeszłego; to nadal dzieje się teraz i problem (dwa lata) wciąż musi jeszcze zostać rozwiązany. * wąchaj *
Lekkość ściga się na orbicie
1
Argumentowałbym, że przyzwoita baza kodu powinna ułatwić pisanie jednorazowego skryptu przy użyciu warstwy trwałej z aplikacji przynajmniej tak szybko, jak pisanie surowego SQL. „Modyfikowanie kodu aplikacji” nigdy nie powinno być konieczne w przypadku jednorazowych skryptów.
Jonathan Cast
17

Powinieneś mieć relacje w bazie danych.

Jak zauważa inna odpowiedź, wydajność sprawdzania ograniczeń będzie znacznie lepsza w tej bazie danych niż w aplikacji. Sprawdzanie ograniczeń bazy danych jest jedną z rzeczy, w których bazy danych są dobre.

Jeśli kiedykolwiek potrzebujesz dodatkowej elastyczności - np. Zanotowanych odniesień do bazy danych - możesz usunąć ograniczenia umyślnie i rozważnie. Spójność w bazie danych oznacza, że ​​masz możliwość modyfikacji tych ograniczeń i pewność integralności referencyjnej.

Kirk Broadhurst
źródło
1
Prawdziwe. Powinienem powiedzieć, że wydajność sprawdzania ograniczeń będzie lepiej obsługiwana w bazie danych niż w aplikacji.
Kirk Broadhurst,
13
  • Nie żyjemy już w jednym świecie back-end <-> jednym świecie front-end.
  • Większość rozwiązań obejmuje interfejs internetowy, interfejs mobilny, interfejs wsadowy, interfejs iPada itp.
  • Silniki baz danych mają już tysiące przetestowanych linii kodu zoptymalizowanych pod kątem wymuszania integralności referencyjnej.

Czy naprawdę stać Cię na pisanie i testowanie kodu egzekwowania integralności referencyjnej, gdy masz kod do rozwiązywania problemów z domeną?

Tulains Córdova
źródło
2
„Nie żyjemy już w jednym świecie zaplecza <-> w jednym świecie”. Czy kiedykolwiek Kilka lat temu pracowałem nad systemem baz danych, który miał dostęp do programów napisanych w co najmniej dwóch tuzinach różnych języków. Niektóre programy miały swoje pierwsze wydanie w latach siedemdziesiątych.
Mike Sherrill „Cat Recall”
2

Jeśli nie sprawdzisz integralności danych, ograniczeń, relacji itp. Na poziomie bazy danych, oznacza to, że każdy, kto ma dostęp do produkcyjnej bazy danych (za pośrednictwem dowolnego innego klienta, w tym narzędzia dostępu do bazy danych), może znacznie łatwiej popsuć dane.

Dobrą praktyką jest egzekwowanie jak najściślejszej integralności danych na poziomie bazy danych. Zaufaj mi, zaoszczędzi to z czasem ogromnych bólów głowy w każdym nietrywialnym systemie. Będziesz także szybciej wychwytywać błędy logiczne aplikacji lub błędy wymagań biznesowych i niespójności, jeśli się nad tym zastanowisz.

Na marginesie należy zaprojektować bazę danych w sposób możliwie najbardziej znormalizowany i atomowy. Brak tabel „Boga”. Poświęć dużo wysiłku, aby twoja baza danych była jak najprostsza, najlepiej z wieloma małymi tabelami, które są indywidualnie bardzo dobrze zdefiniowane, z jedną odpowiedzialnością i dokładnie sprawdzone we wszystkich kolumnach. Baza danych jest ostatnim strażnikiem integralności danych. Reprezentuje Twierdzę Zamku.

Brad Thomas
źródło
1

Większość ludzi zasadniczo mówi „tak, generalnie zawsze będziesz definiować relacje w bazie danych”. Ale gdyby dyscypliny informatyczne były tak łatwe, nazwalibyśmy się „Software Manual Readers” zamiast „Software Engineers”. W rzeczywistości zgadzam się, że ograniczenia powinny iść do bazy danych, chyba że istnieje dobry powód, dla którego nie powinny , dlatego przedstawię kilka powodów, które można uznać za dobre w pewnych sytuacjach:

Duplikat kodu

Czasami w kodzie aplikacji będzie naturalnie istniała pewna ilość funkcji, którą mogłaby obsłużyć baza danych. Jeśli dodanie czegoś takiego jak ograniczenia do bazy danych byłoby zbędne, może być lepiej nie powielać funkcjonalności, ponieważ naruszasz zasady DRY, a możesz pogorszyć żonglujący akt utrzymywania synchronizacji bazy danych i kodu aplikacji.

Wysiłek

Jeśli Twoja baza danych już działa tak, jak powinna, bez korzystania z zaawansowanych funkcji, warto ocenić, gdzie należy poświęcić czas, pieniądze i wysiłek. Jeśli dodanie ograniczeń zapobiegnie katastrofalnej awarii, a tym samym zaoszczędzi Twojej firmie dużo pieniędzy, to prawdopodobnie warto. Jeśli dodajesz ograniczenia, które powinny obowiązywać, ale gwarantują, że nigdy nie zostaną naruszone, tracisz czas i zanieczyszczasz bazę kodu. Gwarantowane jest tutaj słowo operacyjne.

Wydajność

Zwykle nie jest to dobry powód, ale w niektórych przypadkach możesz mieć pewne wymagania dotyczące wydajności. Jeśli kod aplikacji może zaimplementować określoną funkcjonalność w szybszy sposób niż baza danych, a potrzebujesz dodatkowej wydajności, może być konieczne zaimplementowanie tej funkcji w kodzie aplikacji.

Kontrola

Nieco związane z wydajnością. Czasami potrzebujesz bardzo drobiazgowej kontroli nad tym, jak funkcja jest implementowana, a czasem obsługa bazy danych ukrywa ją za czarną skrzynką, którą musisz otworzyć.

Punkty końcowe

  • Bazy danych są zapisane w kodzie. Nie robią nic magicznego, czego nie można zrobić we własnym kodzie.
  • Nic nie jest darmowe. Ograniczenia, relacje itp. Wykorzystują cykle procesora.
  • Ludzie w świecie NoSQL dobrze sobie radzą bez tradycyjnych funkcji Relational. Na przykład w MongoDB struktura dokumentów JSON jest wystarczająca do obsługi całej bazy danych.
  • Ślepe i ignoranckie korzystanie z zaawansowanych funkcji bazy danych nie gwarantuje żadnych korzyści. Możesz przypadkowo sprawić, by coś zadziałało, aby później to zepsuć.
  • Zadałeś bardzo ogólne pytanie, nie wymieniając konkretnych wymagań ani ograniczeń. Prawdziwa odpowiedź na twoje pytanie brzmi „to zależy”.
  • Nie określono, czy był to problem na skalę przedsiębiorstwa. Inne odpowiedzi mówią o rzeczach takich jak klienci i integralność danych, ale czasami te rzeczy nie są ważne.
  • Zakładam, że mówisz o tradycyjnej bazie danych SQL Relational.
  • Moja perspektywa wynika z odejścia od używania ton ograniczeń i kluczy obcych w małych projektach (do 50 tabel) i nie dostrzegania żadnych wad .

Ostatnią rzeczą, którą powiem, jest to, że będziesz wiedział, czy nie powinieneś umieszczać funkcji w bazie danych. Jeśli nie masz pewności, prawdopodobnie lepiej będzie skorzystać z funkcji bazy danych, ponieważ zwykle działają one naprawdę dobrze.

parker.sikand
źródło
1
Jeśli ludzie głosują za przemyślanymi odpowiedziami, ponieważ nie zgadzają się z ich dogmatem, SE StackExchange staje się gorszym miejscem.
Carl Leth,
5
Przesłanka tej odpowiedzi, że są sytuacje, w których możesz pozostawić ograniczenia DB, jest poprawna, ale wyjaśnienie jest słabe i wprowadza w błąd. Chociaż zgadzam się, że baza danych nie jest najlepszym miejscem dla niektórych ograniczeń, żadna relacyjna baza danych nie powinna obejść się bez podstawowego klucza i ograniczeń integralności referencyjnej . Żaden . Nie ma w tym wyjątku. Każda baza danych będzie potrzebować kluczy podstawowych, a zdecydowana większość będzie potrzebować kluczy obcych. Te powinny zawsze być egzekwowane przez bazę danych, nawet jeśli powiela logikę. To, że się nad tym zastanawiasz, jest powodem, dla którego przegłosowałem.
jpmc26
1
„Bazy danych są zapisane w kodzie. Nie robią nic magicznego, czego nie można zrobić we własnym kodzie”. , nie, nie możesz wymusić integralności referencyjnej w kodzie aplikacji (a jeśli nie musisz tego wymuszać, dlaczego w ogóle używasz serwera bazy danych?). Nie chodzi o to, co może zrobić kod, ale o to, gdzie można to zrobić.
hyde
0

Jak zawsze jest wiele odpowiedzi. Dla mnie znalazłem prostą zasadę (dobrze działa tylko w przypadku podejścia zorientowanego na model). Zwykle koncentruję się tylko na różnych warstwach aplikacji.

Jeśli model składa się z kilku podmiotów i istnieją między nimi zależności, warstwa trwałości powinna odzwierciedlać te zależności wraz z ich możliwościami. Więc jeśli używasz RDBMS, powinieneś również użyć kluczy obcych. Powód jest prosty. W ten sposób dane są zawsze poprawne strukturalnie.

Każda instancja wykonująca pracę na tej warstwie trwałości może na niej polegać. Zakładam, że hermetyzujesz tę warstwę za pomocą interfejsu (usługi). Oto punkt, w którym kończy się projektowanie i zaczyna się prawdziwy świat.

Patrząc na swoje punkty, zwłaszcza odniesienia między bazami danych . W takim przypadku tak nie powinno być zaimplementowane odwołanie w samym RDBMS, ale w usłudze. Ale czy przed pójściem w ten sposób nie byłoby lepiej rozważyć to już podczas projektowania?

Znaczy, jeśli już wiem, że istnieją części, które muszą być przechowywane w innym DB, to mogę je już tam umieścić i zdefiniować jako osobny model. Dobrze?

Wskazujesz również, że implementacja tego w kodzie jest bardziej elastyczna . Zgadza się, ale czy to nie brzmi, jakbyś miał do czynienia z niepełnym projektem? Zadaj sobie pytanie, dlaczego potrzebujesz większej elastyczności?

Problem z wydajnością wynikający z kontroli integralności w bazie danych nie jest prawdziwy. RDBMS może sprawdzić takie rzeczy znacznie szybciej niż jakakolwiek implementacja przez ciebie. Dlaczego? Cóż, musisz poradzić sobie z zakłóceniami mediów, RDBMS nie. I może zoptymalizować takie kontrole, używając swoich statystyk aso

Widzisz, wszystko wraca do projektowania. Oczywiście możesz powiedzieć teraz, ale co, jeśli pojawi się nieznany wymóg, zmieniacz gier? Tak, może się zdarzyć, ale takie zmiany powinny zostać zaprojektowane i zaplanowane aso. ; o)

DHN
źródło
0

Masz kilka bardzo dobrych odpowiedzi, ale więcej punktów

Integralność danych jest tym, do czego służy baza danych

Wykonanie odpowiedniej współbieżności, takiej jak usuwanie FK na poziomie aplikacji, byłoby przerażające

Specjalizacja w zakresie integralności danych opiera się na DBA

Na poziomie programu wstawiasz, aktualizujesz, aktualizujesz zbiorczo, wstawiasz zbiorczo, kasujesz zbiorczo ...
Cienki klient, gruby klient, klient mobilny ....
Integralność danych nie jest wiedzą programisty - dużo duplikatu kodu i ktoś będzie bałagan to w górę

Powiedzmy, że zostałeś zhakowany - i tak masz kłopoty, ale haker może wyrządzić wiele szkód przez małą dziurę, jeśli w bazie danych nie ma ochrony integralności

Może być konieczne manipulowanie danymi bezpośrednio za pomocą SQL lub TSQL.
Nikt nie zapamięta wszystkich reguł dotyczących danych

paparazzo
źródło
0

Twoje pytanie nie ma sensu: jeśli możesz zmienić bazę danych, to jest kod, jeśli nie możesz zmienić bazy danych, będziesz musiał stworzyć ograniczenia gdzie indziej.

Baza danych, którą możesz zmienić, to tyle samo kodu, co dowolna linia ruby, javascript, c # lub ada.

Pytanie o miejsce ograniczenia w systemie powinno sprowadzać się do niezawodności, kosztów i łatwości rozwoju.

jmoreno
źródło
0

Tutaj jest mnóstwo dobrych odpowiedzi. Dodam, że jeśli masz aplikację napisaną w języku Y, możesz utworzyć kod podobny do bazy danych w Y. A następnie ktoś chce uzyskać dostęp do Twojej bazy danych w języku Z, musisz ponownie napisać ten sam kod. Niech Bóg ci pomoże, jeśli implementacje nie są dokładnie takie same. Lub gdy doświadczony użytkownik biznesowy połączy się z bazą danych za pomocą Microsoft Access.

Z mojego doświadczenia wynika, że ​​kiedy ludzie nie chcą używać ograniczeń bazy danych, to dlatego, że faktycznie próbują zrobić coś w niewłaściwy sposób. Na przykład próbują masowo ładować dane i na jakiś czas chcą pozostawić kolumny inne niż null. Zamierzają „naprawić to później”, ponieważ sytuacja, która spowodowała, że ​​ograniczenie niepuste ma krytyczne znaczenie „nie może się zdarzyć w tym przypadku”. Innym przykładem może być próba połączenia dwóch różnych typów danych w tej samej tabeli.

Bardziej doświadczeni ludzie cofną się o krok i znajdą rozwiązanie, które nie wymaga próby ominięcia ograniczenia. Rozwiązaniem może być po prostu ograniczenie, które nie jest już właściwe, ponieważ firma oczywiście się zmieniła.

Tony Ennis
źródło