Co jest nie tak z kluczami obcymi?


259

Pamiętam, jak Joel Spolsky wspomniał w podcastie 014 , że prawie nigdy nie używał klucza obcego (o ile dobrze pamiętam). Wydaje mi się jednak, że dość istotne jest unikanie powielania i problemów z integralnością danych w całej bazie danych.

Czy ludzie mają jakieś solidne powody, dla których (aby uniknąć dyskusji w zgodzie z zasadami przepełnienia stosu)?

Edycja: „Nie mam jeszcze powodu, aby utworzyć klucz obcy, więc może to być mój pierwszy powód, aby go rzeczywiście skonfigurować”.


9
Nie sądzę, aby Joel nie używał FK, po prostu nie zmuszał bazy danych do ich egzekwowania. Logicznie rzecz biorąc, nadal są FK!
Daren Thomas

6
Mówi, że nie używa obcych kluczy, ale zgadzam się z Darenem, że chodzi mu o to, że nie używa obcych kluczy OGRANICZENIA. Kolumna w jednej tabeli, której wartości należy pobrać z klucza podstawowego / unikalnego innej tabeli, są kluczami obcymi, niezależnie od tego, czy dodasz ograniczenie, czy nie.
Tony Andrews,

22
... Zasadniczo głupotą jest nie dodawanie ograniczenia: ZAWSZE zapewnia integralność, nawet jeśli w kodzie aplikacji występuje błąd lub pracujesz za sceną, wykonując „naprawę” danych.
Tony Andrews,

2
+1 Za komentarz Tony'ego. Istnieje zbyt duże zamieszanie między funkcją a logiczną koncepcją kluczy obcych.
JohnFx

4
@ DanMan, nie wiem, skąd masz wrażenie, że tak myślę. Mówię wyżej: „Generalnie głupotą jest nie dodawanie ograniczenia: to ZAWSZE zapewnia integralność”
Tony Andrews,

Odpowiedzi:


352

Powody używania kluczy obcych:

  • nie dostaniesz osieroconych rzędów
  • możesz uzyskać ładne zachowanie „po kasowaniu kaskadowym”, automatycznie czyszcząc tabele
  • wiedza o relacjach między tabelami w bazie danych pomaga Optymalizatorowi zaplanować zapytania w celu najbardziej wydajnego wykonania, ponieważ jest on w stanie uzyskać lepsze oszacowania liczności złączeń.
  • FK podają dość dużą wskazówkę, które statystyki są najważniejsze do zebrania w bazie danych, co z kolei prowadzi do lepszej wydajności
  • umożliwiają wszelkiego rodzaju automatyczne generowanie wsparcia - ORM mogą się generować, narzędzia do wizualizacji będą w stanie stworzyć dla Ciebie ładne układy schematów itp.
  • ktoś nowy w projekcie szybciej wejdzie w bieg rzeczy, ponieważ w innym przypadku domniemane relacje są jawnie udokumentowane

Powody, dla których nie należy używać kluczy obcych:

  • sprawiasz, że DB działa dodatkowo na każdą operację CRUD , ponieważ musi sprawdzać spójność FK. Może to być duży koszt, jeśli masz dużo rezygnacji
  • wymuszając relacje, FK określają kolejność dodawania / usuwania rzeczy, co może prowadzić do odmowy przez DB wykonania tego, co chcesz. (To prawda, że ​​w takich przypadkach starasz się stworzyć Osierocony Rząd, co zwykle nie jest dobre). Jest to szczególnie bolesne, gdy wykonujesz duże aktualizacje wsadowe i ładujesz jedną tabelę przed drugą, przy czym druga tabela tworzy spójny stan (ale czy powinieneś to robić, jeśli istnieje możliwość, że drugie ładowanie się nie powiedzie i baza danych jest teraz niespójna?).
  • czasami wiesz wcześniej, że Twoje dane będą brudne, akceptujesz to i chcesz, aby DB je zaakceptował
  • jesteś po prostu leniwy :-)

Myślę (nie jestem pewien!), Że większość ustanowionych baz danych umożliwia określenie klucza obcego, który nie jest egzekwowany i jest po prostu odrobiną metadanych. Ponieważ brak egzekwowania wymazuje wszystkie powody, dla których nie należy używać FK, prawdopodobnie powinieneś pójść tą drogą, jeśli którykolwiek z powodów opisanych w drugiej sekcji ma zastosowanie.


12
Dobra lista! DBM nie sprawdzą spójności części CRUD „R”, więc bym ją wyjął. Ponadto jest to prawdopodobnie mycie, ponieważ w aplikacji robisz to samo, co robi DBMS: sprawdzisz i upewnisz się, że identyfikator nadrzędny jest ważny przed CRD, a to jest faktycznie wolniejsze niż w przypadku DBM!
Matt Rogish

6
Co się stanie, jeśli ktoś usunie rodzica podczas wstawiania dzieci? Właśnie teraz, gdy przesyłam „dodaj komentarz” - jeśli już usunąłeś swoją odpowiedź, ten komentarz jest teraz sierotą. FK by temu zapobiegli. Mógłbym również zmienić wartość parentID na dowolną. Ktoś musi to sprawdzić. :)
Matt Rogish

7
Dokładnie - to powinno być zadanie DB, ponieważ jako jedyne może zagwarantować transakcyjność w obliczu wielu współbieżnych klientów.
SquareCog,

3
+1 Doskonała odpowiedź - drugi powód, aby nie używać ograniczenia FK mogłyby być traktowane „utrudnia konsystencji break”, który faktycznie brzmi jak dobra rzecz!
Bill Karwin

9
Korzyści z używania kluczy obcych FAR przewyższają korzyści wynikające z ich nieużywania.
Nick Bedford

80

To kwestia wychowania. Jeśli gdzieś w swojej karierze edukacyjnej lub zawodowej spędziłeś czas karmiąc i dbając o bazy danych (lub ściśle współpracowałeś z utalentowanymi ludźmi, którzy to zrobili), wówczas podstawowe zasady bytów i relacji są dobrze zakorzenione w twoim procesie myślowym. Wśród tych podstaw jest, jak / kiedy / dlaczego określać klucze w bazie danych (podstawowe, obce i być może alternatywne). To druga natura.

Jeśli jednak nie miałeś w przeszłości tak dokładnego lub pozytywnego doświadczenia z przedsięwzięciami związanymi z RDBMS, prawdopodobnie nie byłeś narażony na takie informacje. A może twoja przeszłość obejmuje zanurzenie w środowisku, które głośno było anty-bazodanowe (np. „Te DBA to idioci - my nieliczni, wybraliśmy kilka procerów kodu java / c # uratuje dzień”), w którym to przypadku możesz być zdecydowanie przeciwny do tajemnych bełkotów jakiegoś dweeba, które mówią ci, że FK (i ograniczenia, które mogą implikować) naprawdę są ważne, jeśli tylko posłuchasz.

Większość dzieci była uczona, kiedy były dziećmi, że mycie zębów było ważne. Czy dasz sobie radę bez tego? Jasne, ale gdzieś poniżej będzie mniej dostępnych zębów, niż gdybyś mył po każdym posiłku. Gdyby mamy i tatusiowie byli wystarczająco odpowiedzialni, aby objąć projekt bazy danych oraz higienę jamy ustnej, nie prowadzilibyśmy tej rozmowy. :-)


61
Zamierzam użyć destylowanego „klucze obce są jak mycie zębów: śmiało, bez niego, ale ostrożnie, kiedy się uśmiechasz”
Mark Sowul

5
Osobiście uważam, że zasady RDBMS są znacznie prostsze i znacznie lepiej zdefiniowane niż zasady higieny jamy ustnej
Ali Gangji

Za 10 lat na pewno będę rozmawiać o projekcie bazy danych z moim synem / córką, aby nie bałaganił i nie stał się przyczyną następnej awarii na ścianie z powodu problemu z bazą danych.
VarunAgw

52

Jestem pewien, że istnieje wiele aplikacji, w których można to zrobić, ale nie jest to najlepszy pomysł. Nie zawsze możesz liczyć na to, że Twoja aplikacja będzie poprawnie zarządzać bazą danych, a szczere zarządzanie bazą danych nie powinno mieć większego znaczenia dla Twojej aplikacji.

Jeśli używasz relacyjnej bazy danych, wydaje się, że powinieneś mieć w niej określone relacje . Niestety, takie podejście (nie potrzebujesz kluczy obcych) wydaje się być akceptowane przez wielu programistów aplikacji, którzy wolą nie zajmować się niemądrymi rzeczami, takimi jak integralność danych (ale muszą, ponieważ ich firmy nie mają dedykowanych programistów baz danych). Zwykle w bazach danych ułożonych według tych typów masz szczęście, że posiadasz klucze podstawowe;)


26
Naprawdę nie mam ludzi, którzy nie mają FK w swojej bazie danych. Ostatnim razem, gdy pracowałem z kimś, kto go nie miał, powiedział „nie, wymuszamy to w aplikacji”. Tyle że zrobiłem ankietę we wszystkich bazach danych klientów i okazało się, że większość z nich ma sieroty ...
ErikE

1
Zwykle wydaje się, że tak jest. Myślę, że możesz uniknąć egzekwowania TYLKO w bazie danych (o ile użytkownicy nie mają nic przeciwko wyjątkom w czasie wykonywania), ale posiadanie obu jest naprawdę jedyną drogą.
AlexCuse,

To wszystko w transkryptach / odpowiedzi Atwooda „Atwood: ... na podstawie kluczy obcych, które ustawiłeś w indeksach, oni to rozgryzają ... Spolsky: [śmiech] Zakładając, że to robisz. Atwood: Cóż, zakładając, że to robisz poprawnie skonfigurowałeś bazę danych ... ”
MemeDeveloper

4
Baza danych nie jest nazywana relacyjną z powodu relacji między tabelami (KAŻDY rodzaj bazy danych ma jakieś relacje między jednostkami!), Ale ponieważ same tabele są relacjami , w kategoriach matematycznych. Zobacz Wikipedia .
Massimiliano Kraus,

41

Klucze obce są niezbędne w każdym modelu relacyjnej bazy danych.


54
Model tak. Implementacja, która nie jest niezbędna, po prostu prawdopodobnie przydatna.
dkretz

4
Przykro nam, ale głównym powodem, dla którego twórcy aplikacji nie korzystają z obiektowych systemów zarządzania bazami danych (czyli baz danych NoSQL!), Jest inwestycja w RDBMS. Przez większość czasu baza danych (nie system zarządzania bazą danych) jest modelem obiektów warstwy pośredniej, często obejmującym rozproszone pamięci podręczne. I tu właśnie musi nastąpić kaskadowe usunięcie, własność i synchronizacja zmian. RDBMS jest używany przede wszystkim do utrwalania tego modelu obiektowego, a zwykle po żmudnym i praktycznie bezwartościowym ćwiczeniu ORM. Modele relacji są przez większość czasu niepotrzebne!
Sentinel,

2
nie, klucze obce nie są obowiązkowe, aby wskazać „relacyjny”
Silver Moon

To tak naprawdę niewiele wyjaśnia.
Nae

29

Zawsze ich używam, ale potem tworzę bazy danych dla systemów finansowych. Baza danych jest krytyczną częścią aplikacji. Jeśli dane w finansowej bazie danych nie są całkowicie dokładne, to tak naprawdę nie ma znaczenia, ile wysiłku włożono w projekt kodu / interfejsu użytkownika. Po prostu marnujesz swój czas.

Istnieje również fakt, że wiele systemów na ogół musi bezpośrednio łączyć się z bazą danych - od innych systemów, które po prostu odczytują dane (Crystal Reports), po systemy wstawiające dane (niekoniecznie za pomocą zaprojektowanego przeze mnie interfejsu API; może być napisane przez tępy menedżer, który właśnie odkrył VBScript i ma hasło SA do pola SQL). Jeśli baza danych nie jest tak odporna na idiotyzm, jak to tylko możliwe, baza danych do widzenia.

Jeśli twoje dane są ważne, to tak, użyj kluczy obcych, stwórz zestaw procedur przechowywanych, aby wchodzić w interakcje z danymi i zrobić najtrudniejszą bazę danych, jaką możesz. Jeśli twoje dane nie są ważne, dlaczego tworzysz bazę danych na początek?


2
Niezły wgląd. Twierdziłbym, że dane są tak ważne dla każdej aplikacji, która faktycznie jest używana. Jedyną różnicą są konsekwencje uszkodzenia danych. Są wysokie jak na twoją aplikację ...
Jay Godse

20

Aktualizacja : Zawsze używam teraz kluczy obcych. Moja odpowiedź na zarzut „skomplikowane testowanie” brzmi „napisz swoje testy jednostkowe, aby w ogóle nie potrzebowały bazy danych. Wszelkie testy, które korzystają z bazy danych, powinny z niej właściwie korzystać, w tym także klucze obce. Jeśli instalacja jest bolesna, znajdź mniej bolesny sposób przeprowadzenia konfiguracji ”.


Klucze obce komplikują automatyczne testowanie

Załóżmy, że używasz kluczy obcych. Piszesz automatyczny test, który mówi: „Kiedy aktualizuję konto finansowe, powinien zapisać zapis transakcji”. W tym teście chodzi tylko o dwie tabele: accountsi transactions.

Jednak accountsma klucz obcy do contractsi contractsma fk do clientsi clientsma fk do citiesi citiesma fk do states.

Teraz baza danych nie pozwoli na uruchomienie testu bez skonfigurowania danych w czterech tabelach, które nie są powiązane z testem .

Istnieją co najmniej dwie możliwe perspektywy:

  • „To dobrze: twój test powinien być realistyczny, a ograniczenia danych będą istnieć w produkcji”.
  • „To zła rzecz: powinieneś być w stanie testować jednostki systemu bez angażowania innych. Możesz dodać testy integracji systemu jako całości”.

Możliwe jest również tymczasowe wyłączenie sprawdzania klucza obcego podczas uruchamiania testów. MySQL przynajmniej to obsługuje .


Zwykle znajduję się tutaj na środkowej ścieżce: używam FK, a następnie piszę metody pomocnicze do testów jednostkowych, które konfigurują DB do obsługi różnych scenariuszy testowych, np. Metodę pomocniczą do wypełniania „miast” i „stanów” dla dowolnych testów które wymagają wypełnienia tych tabel.
joelpt

Być może powinieneś był użyć tabel łączy między niepowiązanymi podmiotami. Lub przejdź dalej - oddzielny DBS: rozważ sytuację w architekturze zorientowanej na usługi lub Microservice, gdzie każdy element (klienci, konta, transakcje) to różne systemy z różnymi DB. Brak FK między nimi jak wszystkie. W takim przypadku należy użyć FKs, aby zapobiec osieroceniu danych w podtabelach dla każdego rodzaju danych.
JeeBee

3
Istnieją również DBMS, które pozwalają na ograniczenia odroczenia, dzięki czemu są sprawdzane tylko po zatwierdzeniu całej transakcji, więc kolejność wstawiania, aktualizacji, usuwania nie ma znaczenia
a_konia_na_nazwa

2
Jeśli testujesz aktualizację z poziomu warstwy biznesowej, w środowisku programistycznym powinna być obecna wersja FK. Po zaktualizowaniu rekordu powinieneś mieć wartości kolumn potrzebne do pomyślnego zakończenia aktualizacji. W przeciwnym razie IMHO twój test nie będzie ważny.
KeyOfJ

3
Twoja baza danych nie powinna nawet brać udziału w testach jednostkowych, powinieneś je wyśmiewać. Byliby oni zaangażowani w testowanie integracji, ale wszelkie problemy związane z kluczami obcymi są czymś, na co natkną się użytkownicy, chyba że je naprawicie.
Andreas Bergström

16

„Mogą sprawić, że usuwanie rekordów stanie się bardziej kłopotliwe - nie można usunąć rekordu„ głównego ”, w którym znajdują się rekordy w innych tabelach, w których klucze obce naruszałyby to ograniczenie.”

Należy pamiętać, że standard SQL określa działania podejmowane po usunięciu lub aktualizacji klucza obcego. Te, o których wiem to:

  • ON DELETE RESTRICT- Zapobiega usunięciu wierszy w drugiej tabeli, które mają klucze w tej kolumnie. Tak właśnie opisał Ken Ray.
  • ON DELETE CASCADE - Jeśli wiersz w drugiej tabeli zostanie usunięty, usuń wszystkie wiersze w tej tabeli, które go dotyczą.
  • ON DELETE SET DEFAULT - Jeśli wiersz w drugiej tabeli zostanie usunięty, ustaw wszelkie klucze obce odnoszące się do niego do wartości domyślnej kolumny.
  • ON DELETE SET NULL - Jeśli wiersz w drugiej tabeli zostanie usunięty, ustaw wszelkie klucze obce odnoszące się do niego w tej tabeli na null.
  • ON DELETE NO ACTION- Ten klucz obcy oznacza tylko, że jest to klucz obcy; mianowicie do użytku w programach mapujących OR.

Te same działania dotyczą również ON UPDATE.

Domyślne wydaje się zależeć od tego serwer, którego używasz.


14

@imphasing - taki sposób myślenia powoduje koszmary związane z konserwacją.

Dlaczego och, dlaczego miałbyś zignorować deklaratywną integralność referencyjną, w przypadku której można zagwarantować , że dane będą co najmniej spójne, na korzyść tak zwanego „egzekwowania oprogramowania”, co w najlepszym razie jest słabym środkiem zapobiegawczym.


Ponieważ zaangażowani programiści nigdy nie rozwiązali problemu, który wymaga nietrywialnego, znormalizowanego modelu relacyjnego. Wiele problemów tego nie robi, szczególnie tego rodzaju, które obfitują w programowanie typu web / „media społecznościowe”, które jest dziś szalone. Jeśli cokolwiek wypłynie z zaplecza struktury ORM, rozwiązuje problem w wersji alfa, mało prawdopodobne jest, aby ktokolwiek pomyślał o modelowaniu danych. Wiele takich problemów jest równie łatwo rozwiązywanych przez sklepy K / V, bazy danych dokumentów lub serializację obiektów prostych.
zxq9

12

Jest jeden dobry powód, aby ich nie używać: jeśli nie rozumiesz ich roli lub sposobu ich użycia.

W niewłaściwych sytuacjach ograniczenia klucza obcego mogą prowadzić do replikacji wypadków przez wodospad. Jeśli ktoś usunie niewłaściwy zapis, jego cofnięcie może stać się gigantycznym zadaniem.

I odwrotnie, gdy trzeba coś usunąć, jeśli źle zaprojektowane, ograniczenia mogą powodować wszelkiego rodzaju blokady, które ci uniemożliwiają.


8
Usunięcie wiersza w produkcji bez kopii zapasowej nie jest poprawnym argumentem. Jeśli ich nie rozumiesz, powinieneś rozważyć nauczenie się o tym zamiast go pomijać.
Guillaume,

2
@Gillailla Myślę, że jego odpowiedź była nieco sarkastyczna, nie należy tego rozumieć dosłownie: jeśli ich nie rozumiesz, nie używaj ich. Ale oczywiście powinieneś je zrozumieć i używać.
Benjamin

^ To. Są użytecznymi narzędziami, ale w rękach nowicjusza są niebezpiecznymi narzędziami.
Kent Fredric

11

Nie ma dobrych powodów, aby ich nie używać ... chyba że osierocone rzędy nie są dla ciebie wielkim problemem.


11
Dlaczego osierocone rzędy to wielka sprawa?
Seun Osewa,

2
Co z wielowątkowością? W niektórych sytuacjach mogą powodować koszmar wielowątkowości. W złożonej aplikacji z wieloma wątkami zapisującymi bazę danych, która może napotykać obiekty, które muszą się nawzajem odwoływać, lepiej jest kontrolować spójność referencyjną w logice biznesowej --- szczególnie, jeśli później tabele staną się statyczne.
Keith Pinson,

Zgadzam się. Wolę też mieć rzędy ophan, które mogę później odzyskać, niż wyrzucać je bezlitośnie.
PedroD

4

Większe pytanie brzmi: czy prowadziłbyś z zasłoniętymi oczami? Tak to jest, jeśli opracujesz system bez ograniczeń referencyjnych. Należy pamiętać, że zmieniają się wymagania biznesowe, zmiany w projekcie aplikacji, odpowiednie logiczne założenia w kodzie, sama logika może być refaktoryzowana i tak dalej. Ogólnie rzecz biorąc, ograniczenia w bazach danych są wprowadzane przy współczesnych logicznych założeniach, które wydają się poprawne dla określonego zestawu logicznych twierdzeń i założeń.

W całym cyklu życia aplikacji ograniczenia referencyjne i kontrole danych ograniczają zbieranie danych policyjnych przez aplikację, szczególnie gdy nowe wymagania powodują logiczne zmiany aplikacji.

Tematu tego wykazu - klucz obcy sam w sobie nie „poprawia wydajności”, ani nie „znacząco obniża wydajności” z punktu widzenia systemu przetwarzania transakcji w czasie rzeczywistym. Istnieje jednak zagregowany koszt kontroli ograniczeń w systemie „partii” o dużej objętości. Oto różnica między procesem transakcji w czasie rzeczywistym a partią; przetwarzanie wsadowe - w przypadku gdy zsumowany koszt, ponoszony przez kontrole ograniczenia, kolejno przetwarzanego wsadu stanowi pogorszenie wydajności.

W dobrze zaprojektowanym systemie kontrole spójności danych byłyby przeprowadzane „przed” przetworzeniem partii (jednak wiążą się tu również koszty); dlatego sprawdzanie ograniczeń klucza obcego nie jest wymagane w czasie ładowania. W rzeczywistości wszystkie ograniczenia, w tym klucz obcy, powinny zostać tymczasowo wyłączone do czasu przetworzenia partii.

WYKONANIE QUERY - jeśli tabele są połączone na kluczach obcych, należy pamiętać, że kolumny kluczy obcych NIE SĄ INDEKSOWANE (chociaż odpowiedni klucz główny jest indeksowany z definicji). W tym przypadku indeksowanie klucza obcego, indeksowanie dowolnego klucza i łączenie tabel w indeksowanym pomaga w lepszej wydajności, a nie przez przyłączanie się do nieindeksowanego klucza z ograniczeniem klucza obcego.

Zmiana tematów , jeśli baza danych obsługuje tylko wyświetlanie / renderowanie zawartości witryny itp. I rejestrowanie kliknięć, wówczas baza danych z pełnymi ograniczeniami na wszystkich tabelach jest nadmiernie zabijana dla takich celów. Pomyśl o tym. Większość stron internetowych nawet nie używa do tego bazy danych. W przypadku podobnych wymagań, w których dane są właśnie rejestrowane i nie są przywoływane, powiedzmy, użyj bazy danych w pamięci, która nie ma ograniczeń. Nie oznacza to, że nie ma modelu danych, tak modelu logicznego, ale nie ma fizycznego modelu danych.


Cóż, nie wiem, dlaczego wstawienie 3 podwójnych znaków nowego wiersza zamiast pustych znaków i zmiana dwóch słów się liczy, ponieważ „67% to Jonathan Leffler”, ale nie sądzę, że zrobiłem coś takiego. Główny tekst został napisany przez @jay (użytkownik 183837).
Jonathan Leffler,

Po prostu założyłem, że paragrahps nie będzie tu działał, jak ma to miejsce w większości innych witryn. Więc stawiam to wszystko jako jeden, używając pogrubień do zmiany przepływu.
jasbir L

3

Dodatkowy powód używania kluczy obcych: - Pozwala na większe ponowne wykorzystanie bazy danych

Dodatkowy powód, by NIE używać kluczy obcych: - Próbujesz zablokować klienta w swoim narzędziu, ograniczając jego ponowne użycie.


3

Z mojego doświadczenia wynika, że ​​zawsze lepiej jest unikać używania FK w krytycznych aplikacjach bazodanowych. Nie zgodziłbym się z facetami, którzy twierdzą, że FKs jest dobrą praktyką, ale nie jest to praktyczne, gdy baza danych jest ogromna i ma ogromne operacje CRUD / s. Mogę udostępniać bez nazywania ... jeden z największych banków inwestycyjnych nie ma ani jednego FK w bazach danych. Ograniczenia te są obsługiwane przez programistów podczas tworzenia aplikacji z udziałem DB. Podstawowym powodem jest to, że po każdym nowym CRUD musi on wpływać na wiele tabel i weryfikować dla każdej wstawki / aktualizacji, chociaż nie będzie to duży problem w przypadku zapytań wpływających na pojedyncze wiersze, ale powoduje ogromne opóźnienie, gdy masz do czynienia z przetwarzanie wsadowe, które każdy duży bank musi wykonywać jako codzienne zadania.

Lepiej unikać FK, ale jego ryzyko musi być obsługiwane przez programistów.


8
Nie sądzę, aby praktyki rozwoju w dużych bankach ustanawiały złoty standard.
Adriaan Koster

3

„Przed dodaniem rekordu sprawdź, czy odpowiedni rekord istnieje w innej tabeli” to logika biznesowa.

Oto kilka powodów, dla których nie chcesz tego w bazie danych:

  1. Jeśli reguły biznesowe ulegną zmianie, musisz zmienić bazę danych. Baza danych będzie musiała odtworzyć indeks w wielu przypadkach, co jest powolne w przypadku dużych tabel. (Zmiana zasad obejmuje: zezwól gościom na publikowanie wiadomości lub zezwól użytkownikom na usunięcie konta, mimo opublikowania komentarzy itp.).

  2. Zmiana bazy danych nie jest tak łatwa jak wdrożenie poprawki oprogramowania poprzez wypchnięcie zmian do repozytorium produkcyjnego. Chcemy unikać zmiany struktury bazy danych w jak największym stopniu. Im więcej logiki biznesowej znajduje się w bazie danych, tym bardziej zwiększasz ryzyko konieczności zmiany baz danych (i ponownego zaindeksowania).

  3. TDD. W testach jednostkowych możesz zastąpić bazę danych próbnymi i przetestować funkcjonalność. Jeśli w bazie danych znajduje się jakakolwiek logika biznesowa, nie wykonujesz kompletnych testów i będziesz musiał albo przetestować z bazą danych, albo zreplikować logikę biznesową w kodzie do celów testowych, powielając logikę i zwiększając prawdopodobieństwo, że logika nie będzie działać w ta sama droga.

  4. Ponowne użycie logiki z różnymi źródłami danych. Jeśli w bazie danych nie ma logiki, moja aplikacja może tworzyć obiekty z rekordów z bazy danych, tworzyć je z usługi internetowej, pliku json lub innego źródła. Muszę tylko zamienić implementację mapera danych i mogę korzystać z całej logiki biznesowej z dowolnego źródła. Jeśli w bazie danych jest logika, nie jest to możliwe i należy ją zaimplementować na warstwie mapowania danych lub w logice biznesowej. Tak czy inaczej, potrzebujesz tych czeków w kodzie. Jeśli baza danych nie ma logiki, mogę wdrożyć aplikację w różnych lokalizacjach przy użyciu różnych implementacji bazy danych lub plików płaskich.


2

Zgadzam się z poprzednimi odpowiedziami, ponieważ są one przydatne do zachowania spójności danych. Jednak kilka tygodni temu Jeff Atwood napisał interesujący post, który omawiał zalety i wady znormalizowanych i spójnych danych.

Krótko mówiąc, zdenormalizowana baza danych może być szybsza przy przetwarzaniu dużych ilości danych; i możesz nie dbać o dokładną spójność w zależności od aplikacji, ale zmusza cię to do większej ostrożności przy przetwarzaniu danych, ponieważ DB nie będzie.


Jeff robi dobre rzeczy. Jednak Dan Chak w „Enterprise Rails” pokazuje sposób projektowania tabel pamięci podręcznej, które są zasadniczo zdenormalizowaną kopią danych. Zapytania działają szybko, a jeśli tabela nie musi być odświeżana, działa dobrze. Uważam, że jeśli dane sterują zachowaniem (np. Stanem aplikacji) aplikacji, należy ją w jak największym stopniu znormalizować, ponieważ w przeciwnym razie niespójne dane prowadzą do niespójnego zachowania aplikacji.
Jay Godse

Zdormalizowana hurtownia danych może być przydatna podczas odczytywania dużych ilości danych na spójnych, przewidywanych ścieżkach dostępu . We wszystkich innych scenariuszach jest to niebezpieczny błąd.
Peter Wone

2

Baza danych Clarify to przykład komercyjnej bazy danych, która nie ma kluczy podstawowych ani obcych.

http://www.geekinterview.com/question_details/18869

Zabawne jest to, że dokumentacja techniczna dokłada wszelkich starań, aby wyjaśnić, w jaki sposób powiązane są tabele, jakich kolumn użyć, aby je połączyć itp.

Innymi słowy, mogli dołączyć do tabel z wyraźnymi deklaracjami (DRI), ale nie zdecydowali się .

W związku z tym baza danych Clarify jest pełna niespójności i osiąga gorsze wyniki.

Ale przypuszczam, że ułatwiło to programistom zadanie, bez konieczności pisania kodu, aby radzić sobie z referencyjnością, np. Sprawdzanie powiązanych wierszy przed usunięciem, dodaniem.

Wydaje mi się, że jest to główna zaleta braku ograniczeń klucza obcego w relacyjnej bazie danych. Ułatwia rozwój, przynajmniej z diabelskiego punktu widzenia.


Kod do obsługi nieudanej kontroli integralności referencyjnej jest znacznie mniejszy niż kod do obsługi niespójnych danych.
Jay Godse

@Jay zgadzam się! Nie sądzę, że zalecam takie podejście.
Ed Guiness,

2

Znam tylko bazy danych Oracle, żadnych innych, i mogę powiedzieć, że klucze obce są niezbędne do zachowania integralności danych. Przed wstawieniem danych należy stworzyć strukturę danych i poprawić ją. Po wykonaniu tej czynności - a więc utworzeniu wszystkich kluczy podstawowych i obcych - praca jest wykonywana!

Czyli: osierocone rzędy? Nie. Nigdy tego nie widziałem. Chyba że zły programista zapomniał klucza obcego lub jeśli zaimplementował go na innym poziomie. Oba są - w kontekście Oracle - ogromnymi błędami, które doprowadzą do duplikacji danych, osieroconych danych, a tym samym: uszkodzenia danych. Nie wyobrażam sobie bazy danych bez wymuszonego FK. Dla mnie wygląda to na chaos. To trochę jak system uprawnień Unix: wyobraź sobie, że wszyscy są rootami. Pomyśl o chaosie.

Klucze obce są niezbędne, podobnie jak klucze podstawowe. To jak powiedzenie: co jeśli usuniemy Klucze podstawowe? Nastąpi całkowity chaos. Właśnie to. Nie możesz przenieść odpowiedzialności klucza podstawowego lub obcego na poziom programowania, musi to być na poziomie danych.

Wady Tak, absolutnie! Ponieważ na wkładce będzie miało miejsce znacznie więcej kontroli. Ale jeśli integralność danych jest ważniejsza niż wydajność, nie trzeba się zastanawiać. Problem z wydajnością Oracle jest bardziej związany z indeksami, które pochodzą z PK i FK.


1

Mogą sprawić, że usuwanie rekordów stanie się bardziej kłopotliwe - nie można usunąć rekordu „głównego”, jeśli istnieją rekordy w innych tabelach, w których klucze obce naruszałyby to ograniczenie. Za pomocą wyzwalaczy można usuwać kaskadowo.

Jeśli wybierzesz swój klucz podstawowy nierozsądnie, zmiana tej wartości stanie się jeszcze bardziej skomplikowana. Na przykład, jeśli mam PK mojej tabeli „klientów” jako nazwisko osoby i ustawię ten klucz jako FK w tabeli „zamówień”, jeśli klient chce zmienić swoje imię, to jest to królewski ból. , ale to tylko tandetny projekt bazy danych.

Uważam, że korzyści płynące z używania kluczy Fireign przewyższają wszelkie domniemane wady.


5
Tak czy inaczej rzadko coś usuwam. Tylko znak ma bit „Widoczny / aktywny”.
Dana

+1 za „Wierzę, że zalety używania ognistych kluczy przewyższają wszelkie domniemane wady”
Ian Boyd

2
Nigdy, nigdy nie zmieniasz wartości klucza podstawowego. Ci usunąć cały wiersz i odtworzyć go w inny sposób. Jeśli uważasz, że musisz to zmienić , twój schemat jest wadliwy.
DanMan

Zmiana nazwy klienta wcale nie byłaby kłopotliwa, JEŻELI Twój klucz obcy jest ustawiony na CustomerId (PK). w tabeli zamówień. Jedyny sposób, by to był ból, to ustawienie FK na CustomerName, co nigdy nie powinno mieć miejsca. IMHO
KeyOfJ

1

Weryfikacja ograniczeń klucza obcego zajmuje trochę czasu procesora, więc niektórzy ludzie pomijają klucze obce, aby uzyskać dodatkową wydajność.


6
Ile czasu procesor spędza na usuwaniu zduplikowanych i niespójnych danych?
Ed Guiness,

Tak, to prawda. W systemie, nad którym pracuję, musimy wstawiać 10–40 koncertów danych do bazy danych, a wydajność FK z i bez jest widoczna w łącznym czasie.
Paul Mendoza

1

Słyszałem też ten argument - od osób, które zapomniały umieścić indeks swoich kluczy obcych, a następnie narzekały, że niektóre operacje są powolne (ponieważ sprawdzanie ograniczeń może skorzystać z dowolnego indeksu). Podsumowując: Nie ma dobrego powodu, aby nie używać kluczy obcych. Wszystkie nowoczesne bazy danych obsługują usuwanie kaskadowe, więc ...


9
Uważam, że prawdziwym powodem, dla którego ograniczenia FK nie są stosowane przez niektórych (większość z mojej perspektywy), jest zwykłe lenistwo pod pretekstem, że mogą bronić swojego lenistwa za pomocą argumentu oszczędnościowego. Mocno wierzę, że ogromna większość wydatków na głupotę ponoszonych przez naszą firmę wynika z braku egzekwowania ograniczeń FK i efektu falowania, jaki ma to poprzez firmę. Brak unikalnych kluczy to kolejna rzecz, która doprowadza mnie do szału przy ponad 2000 procedur przechowywanych na linii z 12 poziomami zagnieżdżonych IF i losowym wcięciem, ale teraz przestanę.
Czad

1

Argument, który słyszałem, jest taki, że front-end powinien mieć te reguły biznesowe. Klucze obce „dodają niepotrzebnego narzutu”, kiedy nie należy zezwalać na wstawiania, które w pierwszej kolejności łamią ograniczenia. Czy się z tym zgadzam? Nie, ale to zawsze słyszałem.

EDYCJA: Domyślam się, że miał na myśli ograniczenia klucza obcego , a nie klucze obce jako koncepcję.


Nie. On nie lubi prawdziwych kluczy!
ljs

To mnie zadziwia. Istnieje duża różnica między niepodobaniem się do kluczy obcych a niepodobaniem do kluczy obcych. Nie jestem pewien, jak masz relacyjną bazę danych bez nich.
lordscarlet,

Tak, byłem zszokowany, kiedy go usłyszałem. Mógł jednak nieumyślnie mówić z przymrużeniem oka; być może opublikuje tutaj i wyjaśni na pewnym etapie :-)
ljs 17.09.08

1

Dla mnie, jeśli chcesz przestrzegać standardów ACID , bardzo ważne jest, aby mieć klucze obce, aby zapewnić integralność referencyjną.


1

W tym miejscu muszę zająć większość komentarzy. Klucze obce są niezbędnymi elementami, aby zapewnić rzetelność danych. Różne opcje ON DELETE i ON UPDATE pozwolą ominąć niektóre „spadki”, o których wspominają ludzie, dotyczące ich użycia.

Uważam, że w 99% wszystkich moich projektów będę mieć FK, aby wymusić integralność danych, jednak zdarzają się rzadkie przypadki, w których mam klientów, którzy MUSZĄ zachować swoje stare dane, niezależnie od tego, jak źle jest .... ale potem spędzam dużo czasu na pisaniu kodu, który i tak dostaje tylko prawidłowe dane, więc staje się bezcelowy.


1

Co z utrzymywalnością i stałością w cyklach życia aplikacji? Większość danych ma dłuższą żywotność niż aplikacje, które z nich korzystają. Relacje i integralność danych są zbyt ważne, aby pozostawić nadzieję, że następny zespół deweloperów zajmie się tym w kodzie aplikacji. Jeśli nie pracowałeś na bazie danych z brudnymi danymi, które nie szanują naturalnych relacji, to zrobisz to. Znaczenie integralności danych stanie się wówczas bardzo jasne.


1

Myślę również, że klucze obce są koniecznością w większości baz danych. Jedyną wadą (oprócz pogorszenia wydajności wynikającej z wymuszonej spójności) jest to, że posiadanie klucza obcego umożliwia pisanie kodu, który zakłada, że ​​istnieje funkcjonalny klucz obcy. To nigdy nie powinno być dozwolone.

Na przykład widziałem, jak ludzie piszą kod, który wstawia do tabeli, do której następuje odwołanie, a następnie próbuje wstawić do tabeli, do której się odwołuje, bez sprawdzenia, czy pierwsza wstawka zakończyła się powodzeniem. Jeśli klucz obcy zostanie usunięty później, spowoduje to niespójność bazy danych.

Nie masz również opcji zakładania określonego zachowania podczas aktualizacji lub usuwania. Nadal musisz napisać kod, aby zrobić to, co chcesz, niezależnie od tego, czy jest obecny klucz obcy. Jeśli założysz, że usunięcia są kaskadowe, gdy nie są, usuwanie nie powiedzie się. Jeśli założysz, że aktualizacje odnośnych kolumn są propagowane do wierszy odwołujących, gdy nie są, aktualizacje się nie powiodą. Do celów pisania kodu równie dobrze możesz nie mieć tych funkcji.

Jeśli te funkcje są włączone, kod i tak je emuluje i stracisz trochę wydajności.

Podsumowanie ... Klucze obce są niezbędne, jeśli potrzebujesz spójnej bazy danych. Nigdy nie należy zakładać, że klucze obce są obecne lub działają w pisanym kodzie.


1

Powtarzam odpowiedź Dmitriya - bardzo dobrze ujęta.

Dla tych, którzy martwią się narzutami wydajności, które często przynoszą FK, istnieje sposób (w Oracle) na uzyskanie optymalizatora kwerendy przewagi ograniczenia FK bez narzutu związanego z weryfikacją ograniczeń podczas wstawiania, usuwania lub aktualizacji. To jest tworzenie ograniczenia FK z atrybutami RELY DISABLE NOVALIDATE. Oznacza to, że optymalizator zapytań PRZYKŁADA, że ograniczenie zostało wymuszone podczas budowania zapytań, a baza danych faktycznie nie wymusza ograniczenia. Musisz być bardzo ostrożny, aby wziąć odpowiedzialność za wypełnienie tabeli takim ograniczeniem FK, aby mieć absolutną pewność, że nie masz danych w kolumnach FK, które naruszają ograniczenie, tak jakbyś to robił może uzyskać niewiarygodne wyniki z zapytań dotyczących tabeli, na której jest włączone ograniczenie FK.

Zazwyczaj używam tej strategii na niektórych tabelach w schemacie mart data, ale nie w zintegrowanym schemacie pomostowym. Upewniam się, że tabele, z których kopiuję dane, mają już wymuszone to samo ograniczenie lub procedura ETL wymusza to ograniczenie.


1

Wiele osób, które tu odpowiedziały, zbytnio rozwiewa się na znaczeniu integralności referencyjnej realizowanej za pomocą ograniczeń referencyjnych. Praca na dużych bazach danych z integralnością referencyjną po prostu nie działa dobrze. Oracle wydaje się szczególnie kiepski przy kasowaniu kasowań. Moja ogólna zasada jest taka, że ​​aplikacje nigdy nie powinny aktualizować bazy danych bezpośrednio i powinny odbywać się za pomocą procedury składowanej. Utrzymuje to bazę kodu w bazie danych i oznacza, że ​​baza danych zachowuje integralność.

Tam, gdzie wiele aplikacji może uzyskiwać dostęp do bazy danych, pojawiają się problemy z powodu ograniczeń integralności referencyjnej, ale to zależy od kontroli.

Istnieje również szerszy problem, ponieważ programiści aplikacji mogą mieć bardzo różne wymagania, z którymi programiści baz danych niekoniecznie muszą się zapoznać.


5
„aplikacje nigdy nie powinny aktualizować bazy danych bezpośrednio i powinny odbywać się za pomocą procedury składowanej. Pozwala to zachować bazę kodu wewnątrz bazy danych i oznacza, że ​​baza danych zachowuje integralność” <- Istnieje założenie, że logika w procedurach przechowywanych nie może naruszać integralności danych, co jest po prostu błędne.
Tim Gautier,

1

Jeśli masz absolutną pewność, że jeden podstawowy system bazy danych nie zmieni się w przyszłości, użyłbym kluczy obcych, aby zapewnić integralność danych.

Ale oto kolejny bardzo dobry powód, dla którego w ogóle nie należy używać kluczy obcych:

Tworzysz produkt, który powinien obsługiwać różne systemy baz danych.

Jeśli pracujesz z Entity Framework, który jest w stanie łączyć się z wieloma różnymi systemami baz danych, możesz także chcieć obsługiwać bezserwerowe bazy danych „open-source-free”. Nie wszystkie z tych baz danych mogą obsługiwać reguły kluczy obcych (aktualizacja, usuwanie wierszy ...).

Może to prowadzić do różnych problemów:

1.) Podczas tworzenia lub aktualizacji struktury bazy danych mogą wystąpić błędy. Być może będą tylko ciche błędy, ponieważ twoje klucze obce są po prostu ignorowane przez system bazy danych.

2.) Jeśli polegasz na kluczach obcych, prawdopodobnie wykonasz mniej lub nawet nie będzie sprawdzać integralności danych w logice biznesowej. Teraz, jeśli nowy system bazy danych nie obsługuje tych reguł dotyczących kluczy obcych lub po prostu zachowuje się w inny sposób, musisz przepisać logikę biznesową.

Możesz zapytać: kto potrzebuje różnych systemów baz danych? Cóż, nie każdy może sobie pozwolić na pełny serwer SQL na swoim komputerze. To oprogramowanie, które należy utrzymywać. Inni już zainwestowali czas i pieniądze w inny system DB. Bezserwerowa baza danych jest idealna dla małych klientów na jednym komputerze.

Nikt nie wie, jak zachowują się wszystkie te systemy DB, ale logika biznesowa z kontrolą integralności zawsze pozostaje taka sama.


0

Zawsze myślałem, że leniwie jest ich nie używać. Nauczono mnie, że zawsze należy to robić. Ale potem nie słuchałem dyskusji Joela. Może miał dobry powód, nie wiem.


To była bardziej nieszablonowa uwaga niż dyskusja, chociaż być może powinienem osobiście zbadać, co myśli na ten temat! Byłem jednak ciekawy opinii społeczności na ten temat!
ljs

0

Jednym z przypadków, gdy FK może powodować problem, są dane historyczne, które odwołują się do klucza (w tabeli odnośników), mimo że klucz nie jest już dostępny.
Oczywiście rozwiązaniem jest projektowanie z góry lepiej, ale myślę o sytuacjach w świecie rzeczywistym, w których nie zawsze masz kontrolę nad pełnym rozwiązaniem.
Na przykład: być może masz tabelę przeglądową, customer_typektóra zawiera listę różnych typów klientów - powiedzmy, że musisz usunąć określony typ klienta, ale (z powodu ograniczeń biznesowych) nie są w stanie zaktualizować oprogramowania klienckiego i nikt nie przewidział takiej sytuacji podczas opracowywania oprogramowania fakt, że jest to klucz obcy w innej tabeli, może uniemożliwić usunięcie wiersza, nawet jeśli znasz dane historyczne, które się do niego odwołują, nie ma znaczenia.
Po kilkakrotnym przypaleniu prawdopodobnie odejdziesz od wymuszania relacji przez db db.
(Nie twierdzę, że to jest dobre - podam tylko powód, dla którego możesz zdecydować się na unikanie ograniczeń FK i DB w ogóle)


Jeśli rozumiem, co próbujesz powiedzieć, myślę, że moją odpowiedzią byłoby logiczne usunięcie rekordu w tabeli odnośników lub zarchiwizowanie nieistotnych danych historycznych i zarchiwizowanie również rekordu odnośników.
Czad
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.