Czy złą praktyką jest posiadanie kilku wzajemnie wykluczających się relacji jeden do jednego?

38

Powiedzmy, tabela carma relację jeden-do-jednego do tabel electric_car, gas_cari hybrid_car. Jeśli a carjest electric_car, nie może już pojawiać się w, gas_cara hybrid_caritp.

Czy jest coś złego w takim projekcie? Jakieś problemy, które mogą wystąpić na drodze?

Artur Tarasow
źródło

Odpowiedzi:

59

Różne typy samochodów są przykładem ogólnego problemu, który pojawia się w modelowaniu danych w kółko. Nazywa się to „uogólnieniem / specjalizacją” w modelowaniu ER, a „superklasa / podklasa” w modelowaniu obiektowym.

Modeler obiektów korzysta z funkcji dziedziczenia wbudowanych w model obiektów, aby dość łatwo rozwiązać problem. Podklasy po prostu rozszerzają nadklasę.

Model relacyjny ma do czynienia z problemem. jak zaprojektować tabele, aby naśladować korzyści wynikające z dziedziczenia?

Najprostsza technika nazywa się dziedziczeniem pojedynczej tabeli . Dane o wszystkich typach samochodów są pogrupowane w jedną tabelę dla samochodów. Istnieje kolumna car_type, która grupuje wszystkie samochody jednego typu. Żaden samochód nie może należeć do więcej niż jednego typu. Jeśli kolumna nie ma znaczenia, powiedzmy, samochody elektryczne, pozostanie NULL w wierszach, które dotyczą samochodów elektrycznych.

To proste rozwiązanie działa dobrze w mniejszych i prostszych przypadkach. Obecność dużej liczby wartości NULL w niewielkim stopniu wpływa na ogólne obciążenie pamięci masowej i nieco na ogólne pobieranie. Deweloper może być zmuszony nauczyć się logiki trójwartościowej SQL, jeśli testy logiczne są wykonywane na kolumnach zerowalnych. Na początku może to być zaskakujące, ale można się do tego przyzwyczaić.

Istnieje inna technika, nazywana dziedziczeniem tabeli klas . W tym projekcie istnieją oddzielne tabele dla gas_car, electric_car i hybrid_car, oprócz połączonego stołu, car, dla wszystkich z nich. Jeśli chcesz uzyskać wszystkie dane dotyczące określonego rodzaju samochodu, dołącz do stołu samochodowego odpowiednim stołem specjalistycznym. W tym projekcie jest mniej wartości NULL, ale więcej łączysz. Ta technika działa lepiej w większych i bardziej złożonych przypadkach.

Istnieje trzecia technika zwana wspólnym kluczem podstawowym. Ta technika jest często stosowana w połączeniu z dziedziczeniem tabel klas. Specjalistyczne tabele dla podklas mają jako klucz podstawowy kopię klucza podstawowego odpowiedniego wpisu w tabeli samochodowej. Tę kolumnę identyfikatora można zadeklarować jako klucz podstawowy i klucz obcy.

Wymaga to trochę dodatkowego programowania przy dodawaniu nowych samochodów, ale sprawia, że ​​dołączanie jest proste, łatwe i szybkie.

Nadklasy i podklasy zdarzają się cały czas w prawdziwym świecie. Nie bój się Ale przetestuj swój początkowy projekt pod kątem wydajności. Jeśli Twoja pierwsza próba jest prosta i solidna, będziesz mógł ją ulepszyć, aby przyspieszyć.

Walter Mitty
źródło
3
Wow dziękuję! To jest to, co próbowałem rozgryźć. Dziedziczenie tabel klas wydaje się dokładnie tym, czego potrzebuję. Zmieniłem zaakceptowaną odpowiedź na to dla przyszłych czytelników, ponieważ myślę, że obejmuje ona całkowicie to pytanie, a nie tylko moją sprawę.
Arthur Tarasov,
6
Doskonała odpowiedź tutaj. Jedna wskazówka: dokładnie udokumentuj te decyzje projektowe. Niezależnie od wybranej trasy podjąć, będzie nie być oczywiste, gdy ktoś bada strukturę bazy danych. Niektóre bazy danych, takie jak Postgres, umożliwiają powiązanie komentarza z meta-danymi twoich kolumn, tabel itp.
Basil Bourque,
Nie rozwiązuje się ograniczenia dotyczącego powstrzymywania samochodów elektrycznych również od samochodów hybrydowych. Potrzebujesz do tego osobnego stołu.
jmoreno
2
Masz rację. Jeśli dodasz pole car_type do tabeli samochodów, możesz ograniczyć samochody do przynależności tylko do jednego typu, kosztem odejścia od pełnej normalizacji. Dobry DBMS pozwoli ci zdefiniować ograniczenie sprawdzania, które zapobiegnie wpisaniu samochodu do więcej niż jednej specjalistycznej tabeli. Jest w tym trochę kosztów, idziesz dodać nowe samochody.
Walter Mitty,
@WalterMitty, ale bez car_typepola, skąd miałbyś wiedzieć, której tabeli szukać szczegółów podczas pobierania danych? Czy musisz przeczytać wszystkie trzy tabele, aby zobaczyć, która z nich zawiera dane dotyczące tego konkretnego carrekordu?
Josh Part
12

Nie ma nic złego w tym, że w twoim modelu jest tyle podtypów bytów, ile potrzeba, aby odzwierciedlić rzeczywistość danych, które próbujesz modelować. Pytanie nie dotyczy tego, czy podtypy są złą praktyką. Problemem może być to, czy to dobry model ?

Na przykład, pod twoim przykładem, co robisz z czymś takim jak Audi A4 eTron - która jest hybrydą typu plug-in? Czy to „samochód elektryczny”, czy „samochód hybrydowy”?

Drugim pytaniem, które musisz sobie zadać, jest to, dlaczego w ogóle piszesz na maszynie? Ile różnych predykatów masz w swoich podtypach? Czy któryś z tych predykatów jest wspólny dla podtypów? Sytuacja może się skomplikować.

Podpisywanie nie jest używane w projekcie bazy danych do klasyfikacji. Klasyfikacji można dokonać za pomocą kodów, kluczy obcych do tabel kodów lub flag. Podtypowanie służy do modelowania odrębnych zestawów predykatów dla różnych rodzajów rzeczy będących przedmiotem zainteresowania. Jeśli używasz podtypów tylko do klasyfikacji, to zła praktyka.

Jeśli twoje podtypy w jasny i jednoznaczny sposób modelują różne zestawy predykatów dla rzeczy, o które dba twoja baza danych, jest to całkowicie dobra praktyka, bez względu na to, ile podtypów potrzebujesz.

Joel Brown
źródło
Dzięki, bałam się, że zastawiam na siebie jakąś pułapkę. Mój problem polega na tym, że każdy z podtypów będzie miał wiele kolumn. Niektóre nakładają się na siebie, a ja umieszczam je w cartabeli, ale wielu nie chce i zostanie umieszczonych w tabeli podtypu. Na przykład będzie to coś w rodzaju przechowywania podstawowych części typów samochodów. Silnik samochodu elektrycznego może mieć 100 części, silnik samochodu gazowego 75 części, a hybrydowy 125 części. 50 części mogą być typowe i przechowywać w cars, podczas gdy 50, 25 i 75 będzie electric_car, gas_cari hybrid_cartabele
Arthur Tarasov