Czy te konkretne tabele potrzebują kluczy zastępczych?

13

tło

Mam te tabele

+-------------------------+  +------------------------+
|Airport                  |  |Country                 |
|-------------------------|  |------------------------|
|airport_code string (PK) |  |country_code string (PK)|
|address string           |  |name string             |
|name  string             |  +------------------------+
+-------------------------+

+-------------------------+
|Currency                 |
|-------------------------|
|currency_code string (PK)|
|name string              |
+-------------------------+

kod_portu to kod lotniska IATA (International Air Transport Association) , który można zobaczyć na etykietach bagażowych podczas podróży samolotem.

wprowadź opis zdjęcia tutaj

country_code to standardowy kod kraju ISO 3166-1 A3 , który można zobaczyć na igrzyskach olimpijskich.

wprowadź opis zdjęcia tutaj

currency_code to standardowy 3-znakowy kod waluty IS0 417 , który można zobaczyć na międzynarodowych tablicach wymiany walut.

wprowadź opis zdjęcia tutaj

pytania

Czy te naturalne PK są wystarczająco dobre?

Czy stosowanie uznanych na świecie standardów, które są akceptowane przez całe branże, jest wystarczająco dobre dla PK?

Czy te tabele potrzebują surogatów bez względu na wszystko?

Tulains Córdova
źródło

Odpowiedzi:

15

Nie, nie robią tego. Te klucze są zdecydowanie wystarczająco dobre!

Są wyjątkowe, nie rzadko się zmieni, i sensowne , co jest krokiem w górę ponad klucza zastępczego. To właściwie definicja dobrego PK.

Ograniczenia dotyczące niezmienności PK i liczb całkowitych nie są częścią Modelu Relacyjnego (Codda) ani żadnego standardu SQL (ANSI lub innego).

Bobson
źródło
3
Klucze podstawowe również muszą być niezmienne, coś, czym kody lotniska IATA na pewno nie są. Można je zmienić według kaprysu IATA.
James Snell,
3
@JamesSnell - kody lotnisk IATA są tak samo niezmienne jak kody krajów. Mówisz o zmianie, może raz na dekadę, jeśli tak. Zobacz tutaj na omówienie sprawy. Istnieje wiele przestarzałych kodów, które wciąż istnieją, ponieważ są zbyt trudne do zmiany. Do tego właśnie służy aktualizacja CASCADE. Zmienne klucze podstawowe są uzasadnione, jeśli nie świetna praktyka.
Bobson,
2
@EricKing Ta trzecia strona składa się z przedstawicieli wszystkich głównych partii z wielu branż, następnie standardy są omawiane przez lata, a następnie głosowane aż do osiągnięcia rozsądnego konsensusu. Ponadto uzgadniają mechanizmy, za pomocą których dokonywana jest zmiana lub nowy dodatek. Poza tym standardy list kodowych są tworzone nie pod wpływem kaprysu, ale ponieważ istnieje potrzeba stworzenia kontrolowanej, szanowanej, uzgodnionej listy kodów dla czegoś, aby móc współpracować na całym świecie i prawidłowo komunikować się na całym świecie.
Tulains Córdova
2
@ user61852 - Można powiedzieć, że normy te są wykonane jako klucze podstawowe.
Bobson,
3
@ Bobson: „Istnieje wiele przestarzałych kodów, które wciąż istnieją, ponieważ są zbyt trudne do zmiany” -> być może dlatego, że są to klucze podstawowe?
Maciej
2

Myślę, że potrzeba jest bardzo mocnym słowem iw ścisłym tego słowa znaczeniu tabele prawdopodobnie nie potrzebują kluczy zastępczych .

Gdyby jednak była to moja baza danych, prawdopodobnie i tak dodałbym klucze zastępcze. Niekoniecznie chcę, aby mój projekt bazy danych zależał od grupy stron trzecich (IATA, ISO), niezależnie od tego, jak stabilne są ich standardy. Lub może wcale nie chcę polegać na określonym standardzie (czy istnieją inne standardy kodów walut? Nie wiem). Prawdopodobnie modelowałbym swoje tabele za pomocą kluczy zastępczych w następujący sposób:

+-------------------------+  +------------------------+
|Airport                  |  |Country                 |
|-------------------------|  |------------------------|
|airport_id       int (PK)|  |country_id     int (PK) |
|iata_airport_code string |  |iso_country_code string |
|icao_airport_code string |  +------------------------+
|faa_identifier    string |  
|address           string |  
|name              string |  
+-------------------------+

+-------------------------+
|Currency                 |
|-------------------------|
|currency_id int (PK)     |
|iso_currency_code string |
|name string              |
+-------------------------+

Innymi słowy, chyba że te standardowe kody branżowe są z natury ważne dla mojej aplikacji, nie użyłbym ich jako PK moich tabel. To tylko etykiety. Większość moich innych tabel prawdopodobnie będzie miała klucze zastępcze, a ta konfiguracja zwiększy spójność mojego modelu danych. Koszt „dodania” kluczy zastępczych jest minimalny.

Aktualizacja na podstawie niektórych komentarzy:

Bez znajomości kontekstu przykładowych tabel nie można wiedzieć, jak ważne są na przykład kody IATA Airport dla aplikacji korzystającej z bazy danych. Oczywiście, jeśli kody IATA są centralnie ważne i są szeroko stosowane w całej aplikacji, może być prawidłowa decyzja, po odpowiedniej analizie, użyć kodów jako PK tabeli.

Jeśli jednak tabela jest tylko tabelą wyszukiwania używaną w kilku rogach aplikacji, względne znaczenie kodów IATA może nie uzasadniać tak znaczącego miejsca w infrastrukturze bazy danych. Jasne, być może będziesz musiał wykonać dodatkowe sprzężenie w kilku zapytaniach tu i tam, ale wysiłek ten może być trywialny w porównaniu do wysiłku, jaki trzeba by wykonać, aby upewnić się, że w pełni rozumiesz konsekwencje wprowadzenia kodów IATA pole klucza podstawowego. W niektórych przypadkach nie tylko mnie to nie obchodzi, ale nie chcę dbać o kody IATA. Poniższy komentarz Jamesa Snella jest doskonałym przykładem czegoś, czego nie chciałbym się martwić o wpływ na PK moich stołów.

Ważna jest również konsekwencja w projektowaniu. Jeśli masz bazę danych z dziesiątkami tabel, z których wszystkie mają konsekwentnie zaprojektowane klucze zastępcze, a następnie kilka tabel odnośników, które używają kodów innych firm jako PK, co wprowadza niespójność. Nie jest to wcale takie złe, ale wymaga dodatkowej uwagi w dokumentacji i takie, które mogą nie być uzasadnione. Są to tabele odnośników dla dobra, po prostu użycie klucza zastępczego dla spójności jest całkowicie w porządku.

Aktualizacja na podstawie dalszych badań:

Ok, ugryzła mnie ciekawość i postanowiłem przeprowadzić dla zabawy badania kodów lotniska IATA, zaczynając od linków podanych w pytaniu.

Jak się okazuje, kody IATA nie są tak uniwersalne i autorytatywne, jak się wydaje na pytanie. Według tej strony :

Większość krajów korzysta z czteroznakowych kodów ICAO , a nie kodów IATA, w oficjalnych publikacjach lotniczych.

Ponadto kody IATA i kody ICAO różnią się od kodów identyfikacyjnych FAA , które są jeszcze innym sposobem identyfikacji lotnisk.

Moim celem przywołania tych informacji nie jest rozpoczęcie debaty na temat tego, które kody są lepsze, bardziej uniwersalne, bardziej autorytatywne lub bardziej wyczerpujące, ale aby dokładnie pokazać, dlaczego projektowanie struktury bazy danych wokół dowolnego identyfikatora innej firmy nie jest czymś, co wybrałbym , chyba że istniałby konkretny powód biznesowy .

W tym przypadku uważam, że moja baza danych byłaby lepiej zbudowana, bardziej stabilna i bardziej elastyczna, poprzez rezygnację z kodów IATA (lub dowolnego kodu potencjalnie zmiennego innej firmy) jako kandydata na klucz podstawowy i użycie klucza zastępczego. W ten sposób mogę pominąć wszelkie potencjalne pułapki, które mogą się pojawić z powodu wyboru klucza podstawowego.

Eric King
źródło
1
Więc standardy IATA są wystarczająco dobre dla linii lotniczych, ale nie dla Ciebie?
Tulains Córdova,
1
Oczywiście będziesz musiał dołączyć aż do stolika na lotnisku, jeśli chcesz szukać bagażu z londyńskiego lotniska Heathrow, ponieważ nie możesz tego zrobić select * from baggage where airport_code = 'LHR', co oznacza, że ​​baza danych jest użyteczna tylko do rzucenia aplikacji, która jest bardzo wąska i zastrzeżona podejście, szczególnie gdy właściciel firmy jest tym, który zapłacił za bazę danych, a zatem jest jej właścicielem. Będziesz także musiał napisać kod, aby wykonywać przyziemne czynności, takie jak importowanie danych z jednej bazy danych do drugiej, aby uniknąć kolizji PK.
Tulains Córdova,
1
Kody IATA nie są niezmienne, dlatego nie można ich uważać za kandydatów PK. Przykład: kod IDL był w Nowym Jorku, dopóki nie zmieniono jego nazwy na JFK. Kod IDL jest teraz w stanie Missisipi.
James Snell,
2
@EricKing IATA i ISO dbają o to, aby kody były wystarczająco stabilne, unikalne i powszechnie akceptowane. Jest to zbieżne z zainteresowaniem osoby projektującej stół.
Tulains Córdova
2
@ user61852 - tylko dlatego, że są to standardowe kody, nie oznacza, że ​​system lotniczy używa ich jako PK (może masz więcej wglądu tutaj?). Kaskadowa aktualizacja na tak ogromną skalę wydaje się bardzo złym pomysłem.
JeffO
1

Chociaż posiadanie kluczy zastępczych w polach jest w porządku i nie ma w tym nic złego, czymś do rozważenia może być sam rozmiar strony indeksu.

Ponieważ jest to relacyjna baza danych, będziesz wykonywać wiele połączeń, a posiadanie klucza zastępczego typu liczbowego może ułatwić bazę danych obsługę, tzn. Rozmiar strony indeksu będzie mniejszy, a zatem szybsze wyszukiwanie. Jeśli jest to mały projekt, nie będzie to miało znaczenia i poradzisz sobie bez żadnych problemów, jednak im większa aplikacja, tym bardziej będziesz chciał zmniejszyć wąskie gardła.

Posiadanie BIGINT, INT, SMALLINT, TINYINT lub innego typu danych typu liczb całkowitych może zaoszczędzić ci problemów na drodze.

Tylko moje 2 centy

AKTUALIZACJA:

Mały projekt - z którego korzysta kilka, a może nawet kilkadziesiąt osób. Projekt na małą skalę, projekt demonstracyjny, projekt na użytek osobisty, coś do dodania do portfolio, gdy prezentujesz swoje umiejętności bez doświadczenia i tym podobne.

Duży projekt - z którego korzystają tysiące, dziesiątki tysięcy, miliony użytkowników dziennie. Coś, co zbudowałbyś dla krajowej / międzynarodowej firmy z ogromną bazą użytkowników.

Zwykle zdarza się, że kilka wybranych rekordów jest często wybieranych, a serwer buforuje wyniki w celu szybkiego dostępu, ale co jakiś czas trzeba uzyskać dostęp do mniej używanego rekordu, w którym to momencie serwer musiałby zanurzyć się w indeksie strona. (w powyższym przykładzie z nazwami lotnisk ludzie często latają na krajowe linie lotnicze, np. Chichago -> Los Angeles, ale jak często ludzie latają z Bostonu -> Zimbabwe)

Jeśli używana jest funkcja VARCHAR, oznacza to, że odstępy nie są jednolite, chyba że dane są zawsze tej samej długości (w którym momencie wartość CHAR jest bardziej skuteczna). Powoduje to, że wyszukiwanie indeksu jest wolniejsze, a ponieważ serwer jest już zajęty obsługą tysięcy i tysięcy zapytań na sekundę, teraz musi tracić czas na przeglądanie niejednorodnego indeksu i robić to samo ponownie na sprzężeniach (co jest wolniejsze niż regularne selekcje w niezoptymalizowanej tabeli, weź DW jako przykład, gdzie jest jak najmniej połączeń, aby przyspieszyć pobieranie danych). Również jeśli używasz UTF, który może również zepsuć się z silnikiem bazy danych (widziałem niektóre przypadki).

Osobiście z własnego doświadczenia wynika, że ​​odpowiednio zorganizowany indeks może zwiększyć szybkość łączenia o ~ 70%, a wykonanie połączenia w kolumnie liczb całkowitych może przyspieszyć łączenie nawet o około 25% (w zależności od danych) . Gdy główne tabele zaczną się powiększać i te tabele się na nich przydadzą, wolałbyś, aby typ danych całkowitych zajmował kolumnę, która ma kilka bajtów, zamiast pola VARCHAR / CHAR, które zajmowałoby więcej miejsca. Sprowadza się to do oszczędności miejsca na dysku, zwiększenia wydajności i ogólnej struktury relacyjnej bazy danych.

Ponadto, jak wspomniał James Snell:

Klucze podstawowe również muszą być niezmienne, coś, czym kody lotniska IATA na pewno nie są. Można je zmienić według kaprysu IATA.

Biorąc to pod uwagę, wolałbyś raczej zaktualizować 1 rekord, który jest powiązany z liczbą, zamiast aktualizować ten jeden rekord plus wszystkie rekordy w tabeli, do której dołączasz.

Toni Kostelac
źródło
To słuszna myśl, ale chodzi o to, że w każdej tabeli jest tylko skończona ilość rekordów. Jeśli naprawdę miałeś na myśli rozmiar kodu przez small projecti bigger, zaktualizuj, aby wyjaśnić, dlaczego to ma znaczenie.
Bobson,
1
Ograniczenia dotyczące niezmienności PK i liczb całkowitych nie są częścią Modelu Relacyjnego (Codda) ani żadnego standardu SQL (ANSI lub innego).
Tulains Córdova,
4
Indeksy oparte na stałej długości, krótkich ciągach znaków (takich jak kody ISO) są tak szybkie jak liczby całkowite. Indeksy oparte na zmiennej długości, długie łańcuchy nie są.
Tulains Córdova
Tak powiedziałem (patrz część VARCHAR vs CHAR powyżej) nie miałem okazji przetestować krótkiego łańcucha o ustalonej długości w porównaniu z liczbą całkowitą, ale miałem okazję to zrobić ze zmienną długością i liczbą całkowitą
Toni Kostelac,
2
Dołącz do występu to słaby człowiek. Często używanie naturalnych kluczy oznacza, że ​​nie potrzebujesz łączenia.
Mike Sherrill „Cat Recall”
1

Jeśli zastosujesz podejście „Cały czas używam kluczy zastępczych”, możesz ominąć tego rodzaju obawy. To może nie być dobre, ponieważ ważne jest, aby zastanowić się nad danymi, ale z pewnością oszczędza dużo czasu, energii i wysiłku. Jeśli ktoś miałby przyjąć tę regułę, wymienione przykłady z pewnością się kwalifikują, ponieważ wprowadzenie zmiany wymaga prawie „aktu kongresu”.

Zapytania ad hoc bazy danych z tymi naturalnymi kluczami są z pewnością pomocne. Równie dobrze może działać tworzenie widoków, które robią to samo, włączając tabele odnośników. Nowoczesne bazy danych wykonują znacznie lepszą pracę z tego typu rzeczami do tego stopnia, że ​​prawdopodobnie nie ma to znaczenia.

Istnieją pewne przypadki specyficzne dla USA, w których standardy zostały drastycznie zmienione: kod pocztowy został rozszerzony z 5 - 9 cyfr, skróty stanowe do spójnych 2 liter i pozbył się okresu (pamiętasz, kiedy Illinois był chory?), I większość świat miał do czynienia z Y2K. Jeśli masz aplikację czasu rzeczywistego z rozproszonymi na całym świecie danymi zawierającymi miliardy rekordów, aktualizacje kaskadowe nie są najlepszym pomysłem, ale czy nie powinniśmy wszyscy pracować w miejscach, w których stoją takie wyzwania? Za pomocą tego zestawu danych możesz sam go przetestować i uzyskać bardziej trudną odpowiedź.

JeffO
źródło
+1 Świetna odpowiedź. Przez większość czasu ludzie są bardzo dogmatyczni w tej kwestii. Wielu projektantów baz danych ma ogromne ego i uważa się za właścicieli bazy danych i danych. Inni widzą OK, że właściciel danych może z nich korzystać tylko poprzez określoną aplikację, ponieważ nie może tego zrozumieć. Wolą także tworzyć rezerwy na coś, co może się zdarzyć w przyszłości, lub nie, przy okazji piekła rzeczy, które są wykonywane na co dzień, takich jak importowanie danych i pisanie zapytań. Również nie udało się stworzyć żadnej bibliografii kanonicznej, która popiera ich pogląd.
Tulains Córdova,
Nawiasem mówiąc, reguła „Cały czas używam kluczy zastępczych” nie występuje w modelu relacyjnym (Codda) ani w żadnym standardzie SQL. Schemat słownika danych Oracle wykorzystuje klucze naturalne, gdy tylko jest to możliwe, i klucze sztuczne w innych przypadkach. PPDM ( ppdm.org ) również zaleca podejście mieszane i wykorzystuje je w swoim modelu. ANSI SQL Standard nie mówi nic o surogatach. Myślę, że surogaty i naturalne są żrące. Niektóre naturalne i niektóre surogaty są tym, czego uczy model relacyjny.
Tulains Córdova