Dlaczego nie powinienem mieć jednej tabeli dla wielu relacji?

12

Zakładając, że mam wiele relacji w mojej bazie danych, na przykład Sklep, Pracownik i Sprzedaż, i chcę połączyć pary za pomocą prostej relacji binarnej. Osobiście tworzyłem tabele o nazwie Employee_Store i Employee_Sale z naturalnym kluczem złożonym z kluczy obcych.

Teraz mój kolega nalega na stworzenie jednego stołu dla wielu relacji. W powyższym przykładzie może istnieć tabela o nazwie EmployeeLinks:

EmployeeLinks(
    IdLink int PK, 
    IdEmployee int FK null,
    IdStore int FK null,
    IdSale int FK null,
    LinkType int not null
)

Pomóż mi z ważnymi powodami, dla których nie jest to dobry pomysł. Mam własne argumenty, ale chciałbym zachować ich prywatność i poznać wasze obiektywne opinie.

EDYTOWAĆ:

Początkowo powyższa tabela nie miałaby klucza podstawowego (!). Ponieważ klucze obce umożliwiają zerowanie, klucz zastępczy jest jedyną opcją.

Tomasz Pluskiewicz
źródło
3
Jest jak OTLT lub EAV, ale gorzej, ponieważ rozmnaża kolumny, a nie wiersze!
onedaywhen

Odpowiedzi:

13

Co twój kolega proponuje jako klucz podstawowy dla tej tabeli łączy?
Oczywiście kolumny klucza podstawowego nie mogą mieć wartości NULL: powyższa tabela ma wartość zerową.

W powyższym przykładzie nie ma żadnego naturalnego identyfikatora wiersza (którym jest PK) (kolumna TOŻSAMOŚĆ nie jest kluczem podstawowym), dlatego nie udaje się to w żadnym procesie modelowania. Nawet nie myśl o tworzeniu tabel bez jakiegoś modelu (ERD, ORM, IDEF1X, cokolwiek)

Potrzebujesz również ograniczeń CHECK, aby upewnić się, że nie masz linków trójstronnych.

Wreszcie, zbłądzisz na terytorium czwartej i piątej normalnej formy, ale z niewłaściwych powodów.

Nie mogę znaleźć żadnych przykładów w Internecie: to pokazuje, jak głupie to jest

gbn
źródło
4
+1 zaI can't find any examples on the internet: that shows how stupid this is
JNK
Wyjaśniłem klucz podstawowy. Poza tym podobno mój kolega zetknął się z takim projektem, a przynajmniej tak mi powiedziano
Tomasz Pluskiewicz
@Tomasz Pluskiewicz: Klucz zastępczy nie jest kluczem podstawowym! Jest on wybierany jako uzupełnienie naturalnego klucza w momencie wdrożenia. Zobacz dba.stackexchange.com/a/13779/630 Ponadto twój kolega powinien pokazać nam autorytatywny artykuł, który demonstruje tę technikę. W swoim czasie widziałem pełne stosy śmieci, ale nie powtarzam ich ...
gbn
12

Pierwszym praktycznym powodem, dla którego mogę wymyślić, jest wydajność.

W „tradycyjnym” modelu możesz mieć unikalny indeks na Idemployee, Idstorepolach lub cokolwiek to jest, i uzyskać doskonałą wydajność wyszukiwania. Jest również łatwy w utrzymaniu dla wkładek. Unikalne indeksy sprawiają, że łączenie połączeń jest częstsze, co może znacznie JOINprzyspieszyć.

W twoim przykładowym modelu, aby uzyskać przyzwoitą wydajność, będziesz musiał mieć pojedynczy indeks pól dla każdego pola FK w tabeli, najlepiej indeks obejmujący wszystkie kombinacje, do których będzie się odwoływać, tj .:

  • Pracownik / sklep
  • Pracownik / sprzedaż

Nie jestem pewien, jaki jest typ linku, ale jeśli się do niego odwołujesz, prawdopodobnie powinien zostać zindeksowany.

Te indeksy będą musiały być utrzymywane dla każdego wiersza w tabeli, niezależnie od tego, czy pole jest wypełnione. Możesz dodać filtr, ale przy tak wielu kombinacjach będzie to trudne.

Skomplikuje to również twoją logikę. Musisz albo wyszukać pracownika, znaleźć wiersz z pustą wartością sklepu i zaktualizować; lub po prostu wstaw nowy wiersz dla każdego nowego linku, co w pewnym sensie uniemożliwia konsolidację pól.

Zasadniczo będziesz używać WIĘCEJ miejsca na dysku, utrzymywać MORE indeksy do utrzymania i komplikować logikę bez żadnego powodu. Jedyną „korzyścią” jest to, że jest mniej stolików do czynienia.

JNK
źródło
Kolumna LinkType jest czymś w rodzaju dyskryminatora. Po prostu mówię, która para rzeczywiście odnosi się do rzędu. Po prostu dodaje do urządzenia, jeśli mnie pytasz.
Tomasz Pluskiewicz
@TomaszPluskiewicz Myślę, że najlepszym sposobem, aby pokazać mu, dlaczego jest do bani, jest zbudowanie przykładowego zestawu danych z dwoma rodzajami tabel i uruchomienie niektórych zapytań. Jego model będzie znacznie wolniejszy niż tradycyjny
JNK
4

Umieszczenie wielu relacji w jednej tabeli może być przydatne, jeśli te relacje mają te same atrybuty i / lub jeśli chcesz agregować dane w wielu relacjach.

Jest to konieczne, jeśli typy relacji są zdefiniowane przez użytkownika w czasie wykonywania. Jednak tak naprawdę rzadko tak jest.

W twoim przykładzie relacje nie dzielą atrybutów, a nawet odnoszą się do dwóch różnych tabel. Utrudnia to egzekwowanie ograniczeń, a projekt jest mniej intuicyjny.

Wybrałbym ten projekt tylko wtedy, gdy tworzenie stołów dosłownie kosztuje.

JMD Coalesce
źródło