Złożone klucze podstawowe to zła praktyka? [Zamknięte]

14

Chcę wiedzieć, czy złożone klucze podstawowe są złą praktyką, a jeśli nie, w jakich scenariuszach zaleca się stosowanie.

Moje pytanie opiera się na tym artykule

błędy w projektowaniu baz danych

Część o złożonych kluczach podstawowych:

Zła praktyka nr 6: Złożone klucze podstawowe

Jest to swego rodzaju kwestia kontrowersyjna, ponieważ wielu projektantów baz danych mówi obecnie o używaniu pola generowanego automatycznie liczby całkowitej jako klucza podstawowego zamiast klucza złożonego zdefiniowanego przez kombinację dwóch lub więcej pól. Obecnie jest to określane jako „najlepsza praktyka” i osobiście raczej się z tym zgadzam.

Obraz złożonego klucza głównego

Jest to jednak tylko konwencja i, oczywiście, DBE pozwalają na zdefiniowanie złożonych kluczy podstawowych, które zdaniem wielu projektantów są nieuniknione. Dlatego, podobnie jak w przypadku redundancji, złożone klucze podstawowe są decyzją projektową.

Uważaj jednak, jeśli oczekuje się, że tabela ze złożonym kluczem podstawowym będzie mieć miliony wierszy, indeks kontrolujący klucz złożony może wzrosnąć do punktu, w którym wydajność operacji CRUD jest bardzo obniżona. W takim przypadku o wiele lepiej jest użyć prostego klucza podstawowego z identyfikatorem całkowitym, którego indeks będzie wystarczająco zwarty i ustanowi niezbędne ograniczenia DBE w celu zachowania wyjątkowości.

hackvan
źródło
4
To nie jest „dobra” ani „zła” praktyka. Każda decyzja projektowa musi służyć jednemu celowi; jeśli potrafisz wyjaśnić (sobie i innym), dlaczego potrzebujesz złożonego PK, to dobrze jest iść. I odwrotnie, jeśli potrafisz wyjaśnić, dlaczego go nie potrzebujesz, dobrze jest też iść. Moim zdaniem artykuł, do którego linkujesz, bardzo źle wyjaśnia.
mustaccio
ten artykuł wskazuje na punkt, ale jeśli spojrzymy na popularne frameworki (takie jak na przykład szyny) w swoich „najlepszych praktykach” nie obsługuje tego typu kluczy podstawowych, więc zapytałem dlaczego? dotyczy trudności technicznych lub czegoś innego.
hackvan
Projektom szkieletowym łatwiej jest po prostu obsługiwać „proste” jednokolumnowe klucze podstawowe liczby całkowite. A ponieważ większość programistów (przynajmniej z mojego osobistego doświadczenia) nie ma zbyt wiele umiejętności w zakresie baz danych (przynajmniej w stosunku do użytkowników tej witryny), działa wystarczająco dobrze dla większości użytkowników oprogramowania. Ponieważ większość użytkowników oprogramowania nie potrzebuje kluczy kompozytowych (lub nie sądzi, że potrzebują, przynajmniej na początku), mogą uniknąć (dobrego) wsparcia dla kluczy kompozytowych.
Willem Renzema
1
W jaki sposób GUID jest lepszy niż INTEGER [Szeregowy | Auto_Increment | Tożsamość | <whthing_integer_you_like>]?
Vérace
4
Nie zatrudniłbym tego autora
paparazzo

Odpowiedzi:

31

Powiedzieć, że użycie "Composite keys as PRIMARY KEY is bad practice"jest kompletnym nonsensem!

Kompozyty PRIMARY KEYsą często bardzo „dobrą rzeczą” i jedynym sposobem na modelowanie naturalnych sytuacji występujących w życiu codziennym!

Pomyśl o klasycznym przykładzie nauczania baz danych 101 i uczniach oraz o kursach wielu studentów!

Stwórz tabelę kursu i ucznia:

CREATE TABLE course
(
  course_id SERIAL,
  course_year SMALLINT NOT NULL,
  course_name VARCHAR (100) NOT NULL,
  CONSTRAINT course_pk PRIMARY KEY (course_id)
);


CREATE TABLE student
(
  student_id SERIAL,
  student_name VARCHAR (50),
  CONSTRAINT student_pk PRIMARY KEY (student_id)
);

Dam ci przykład w dialekcie PostgreSQL (i MySQL ) - powinien działać na każdym serwerze z drobnymi poprawkami.

Teraz oczywiście chcą śledzić której uczeń bierze który oczywiście - tak masz, co się nazywa joining table(zwane również linking, many-to-manyczy m-to-ntabele). Znane są również jako associative entitiesw bardziej technicznym żargonie!

1 kurs może mieć wielu studentów.
1 uczeń może wziąć udział w wielu kursach.

Tak więc tworzysz tabelę łączenia

CREATE TABLE course_student
(
  cs_course_id INTEGER NOT NULL,
  cs_student_id INTEGER NOT NULL,

  -- now for FK constraints - have to ensure that the student
  -- actually exists, ditto for the course.

  CREATE CONSTRAINT cs_course_fk FOREIGN KEY (cs_course_id) REFERENCES course (course_id),
  CREATE CONSTRAINT cs_student_fk FOREIGN KEY (cs_student_id) REFERENCES student (student_id)
);

Teraz jedynym sposobem na rozsądne nadanie temu stołowi PRIMARY KEYjest KEYpołączenie tego kursu z uczniem. W ten sposób nie możesz uzyskać:

  • duplikat kombinacji studentów i kursów

    • na kurs może być zapisany tylko jeden uczeń, i

    • student może zapisać się na ten sam kurs tylko raz

  • masz również gotowe wyszukiwanie KEYkursu na ucznia - AKA indeks obejmujący ,

  • znalezienie kursów bez studentów i studentów, którzy nie biorą kursów jest banalne!

    - db-skrzypce przykładem jest ograniczenie PK złożony do tabeli Create - Można to zrobić w obu kierunkach. Wolę mieć wszystko w instrukcji CREATE TABLE.


ALTER TABLE course_student 
ADD CONSTRAINT course_student_pk 
PRIMARY KEY (cs_course_id, cs_student_id);

Teraz, jeśli okaże się, że wyszukiwanie studentów według kursu było powolne, UNIQUE INDEXmożesz użyć opcji on (sc_student_id, sc_course_id).

ALTER TABLE course_student 
ADD CONSTRAINT course_student_sc_uq  
UNIQUE (cs_student_id, cs_course_id);

Nie ma srebrnej kuli do dodawania indeksów - sprawią, że INSERTs i UPDATEs będą wolniejsze, ale z wielką korzyścią ze znacznie krótszychSELECT czasów! Deweloper musi zdecydować o zaindeksowaniu ze względu na swoją wiedzę i doświadczenie, ale stwierdzenie, że kompozyt PRIMARY KEYjest zawsze zły, jest po prostu błędne.

W przypadku łączenia stolików są one zwykle jedyne, PRIMARY KEY które mają sens! Łączenie stołów jest również bardzo często jedynym sposobem modelowania tego, co dzieje się w biznesie, przyrodzie lub w praktycznie każdej sferze, o której myślę!

Ten PK jest również przydatny jako narzędzie, covering indexktóre może przyspieszyć wyszukiwanie. W takim przypadku byłoby szczególnie przydatne, gdybyś regularnie szukał (course_id, student_id), co, jak można sobie wyobrazić, często może mieć miejsce!

To tylko mały przykład, gdzie kompozyt PRIMARY KEYmoże być bardzo dobrym pomysłem i jedynym rozsądnym sposobem modelowania rzeczywistości! Z czubka głowy mogę wymyślić o wiele więcej.

Przykład z mojej własnej pracy!

Rozważmy tabelę lotów zawierającą identyfikator lotu, listę lotnisk odlotów i przylotów oraz odpowiednie czasy, a następnie tabelę personelu pokładowego z członkami załogi!

Jedyny rozsądny sposób ten może być modelowany jest mieć stolik flight_crew z flight_id i crew_id jako atrybuty reklamy i jedynym SANE PRIMARY KEYjest użycie klucza kompozytowego z dwóch pól!

Vérace
źródło
2
w przykładzie kursu i studentów, czy kurs_student może mieć idjako klucz podstawowy i unikalny indeks cs_student_id cs_course_idi mieć takie same wyniki?
hackvan
2
Po co marnować zasoby, robiąc to? Dzięki PK (course_id, student_id) z definicji masz już unikalny indeks na tych polach! Unikalny indeks na (student_id, course_id) może być przydatny do przyspieszenia wyszukiwania - powiedzmy, jeśli szukasz studentów, którzy nie uczęszczają na żadne kursy, ale ta decyzja może być operacyjna, ale w dzisiejszych czasach stosunkowo taniego miejsca do przechowywania, Chciałbym go ponownie wyobrazić, tym bardziej, że można by pomyśleć, że tabela nie będzie często aktualizowana.
Vérace
1
Zgadzam się całkowicie dla tabel linków - pracuję teraz z kilkoma. Jednakże, kiedy zakładam czapkę C #, pracuję z generatorem reversepoco i buduję użyteczne klasy (znajdź, zapisz itp.) Dla następnej warstwy. Uderzyłem w poważny problem - klucze kompozytowe stają się PITA za posiadanie dowolnego ogólnego kodu zapisu / wyszukiwania. Tak, może mógłbym wrócić do plików EDMX, ale nadal muszę obejść albo specjalny kod sprawy (liczyć kolumny Pkey?) Lub dodać sztuczny klucz zastępczy (nie lubię i potrzebuję dodatkowych ograniczeń unikalności :(). ludzie, którzy nie lubią kompozytów, mówią z kodu warstwy aplikacji
Richard Griffiths,
W zależności od częstotliwości wstawek i częstotliwości defragmentacji indeksu w porównaniu z oknem serwisowym jest to lepsze rozwiązanie. Ale niektóre opcje projektowania są kompromisami wynikającymi z wymagań, które mogą nie być natychmiast widoczne. Ale jak powiedział jeden komentarz, zidentyfikuj zalety / wady obu scenariuszy i dokonaj wyboru projektu.
Jonathan Fite
Co dzieje się, gdy uczeń powtarza kurs? Następnie, chyba że kursy rozdzielone w czasie otrzymają różne identyfikatory - masz jeszcze inną tabelę mapowania. Lub dodaj pole daty kursu, które teraz należy dodać do klucza.
iheanyi
3

Moje pół wykształcone zdanie: „klucz podstawowy” nie musi być jedynym unikalnym kluczem używanym do wyszukiwania danych w tabeli, chociaż narzędzia do zarządzania danymi oferują go jako domyślny wybór. Tak więc, aby wybrać, czy jako klucz tabeli ma być złożony z dwóch kolumn, czy losowo generowany (prawdopodobnie szeregowy) numer, możesz mieć dwa różne klucze jednocześnie.

Jeśli wartości danych zawierają odpowiedni unikalny termin, który może reprezentować wiersz, wolę zadeklarować go jako „klucz podstawowy”, nawet jeśli złożony, niż używać klucza „syntetycznego”. Klucz syntetyczny może działać lepiej ze względów technicznych, ale moim własnym domyślnym wyborem jest wyznaczenie i użycie rzeczywistego terminu jako klucza podstawowego, chyba że naprawdę potrzebujesz innej drogi, aby usługa działała.

Microsoft SQL Server ma wyraźną, ale powiązaną funkcję „indeksu klastrowego”, który kontroluje fizyczne przechowywanie danych w kolejności indeksów, a także jest używany w innych indeksach. Domyślnie klucz podstawowy jest tworzony jako indeks klastrowany, ale zamiast tego można wybrać klastrowany, najlepiej po utworzeniu indeksu klastrowego. Możesz więc mieć kolumnę generowaną tożsamość całkowitą jako indeks klastrowany i, powiedzmy, nazwę pliku nvarchar (128 znaków) jako klucz podstawowy. Może to być lepsze, ponieważ klastrowany klucz indeksu jest wąski, nawet jeśli nazwa pliku jest przechowywana jako termin klucza obcego w innych tabelach - chociaż ten przykład jest dobrym przykładem, aby tego nie robić.

Jeśli Twój projekt wymaga importowania tabel danych, które zawierają niewygodny klucz podstawowy w celu identyfikacji powiązanych danych, to prawie utkniesz w tym.

https://www.techopedia.com/definition/5547/primary-key opisuje przykład wyboru, czy przechowywać dane z numerem ubezpieczenia społecznego klienta jako kluczem klienta we wszystkich tabelach danych, czy wygenerować dowolny identyfikator klienta, gdy zarejestruj je. W rzeczywistości jest to poważne nadużycie SSN, niezależnie od tego, czy działa, czy nie; jest to wartość danych osobowych i poufnych.

Zaletą korzystania z faktów ze świata rzeczywistego jest to, że bez ponownego łączenia się z tabelą „Klient” można uzyskać informacje o nich w innych tabelach - ale jest to również kwestia bezpieczeństwa danych.

Masz również problemy, jeśli SSN lub inny klucz danych został nieprawidłowo zapisany, więc masz niepoprawną wartość w 20 ograniczonych tabelach, a nie tylko w „Klient”. Podczas gdy syntetyczny identyfikator_klienta nie ma znaczenia zewnętrznego, więc nie może być złą wartością.

Robert Carnegie
źródło
1
Szczególnie doceniam spostrzeżenie, że w zależności od danych klienta jako klucza, nawet znane unikalne dane klienta (tutaj, SSN), psują się, jeśli dane te kiedykolwiek wymagają korekty.
ToolmakerSteve