Krótka wersja
Muszę dodać stałą liczbę dodatkowych właściwości do każdej pary w istniejącym złączeniu wiele do wielu. Przechodząc do poniższych schematów, który z wariantów 1-4 jest najlepszym sposobem, jeśli chodzi o zalety i wady, aby to osiągnąć poprzez rozszerzenie przypadku podstawowego? Czy jest lepsza alternatywa, której tutaj nie rozważałem?
Dłuższa wersja
Obecnie mam dwie tabele w relacji wiele do wielu za pośrednictwem pośredniej tabeli łączenia. Teraz muszę dodać dodatkowe linki do właściwości należących do pary istniejących obiektów. Mam ustaloną liczbę tych właściwości dla każdej pary, chociaż jeden wpis w tabeli właściwości może dotyczyć wielu par (lub nawet może być użyty wiele razy dla jednej pary). Próbuję ustalić najlepszy sposób na zrobienie tego i mam problem z ustaleniem, jak myśleć o sytuacji. Semantycznie wydaje się, że równie dobrze mogę to opisać jako jedno z poniższych:
- Jedna para połączona z jednym zestawem stałej liczby dodatkowych właściwości
- Jedna para powiązana z wieloma dodatkowymi właściwościami
- Wiele (dwóch) obiektów powiązanych z jednym zestawem właściwości
- Wiele obiektów powiązanych z wieloma właściwościami
Przykład
Mam dwa typy obiektów, X i Y, każdy z unikalnymi identyfikatorami, a łączący tabelę objx_objy
z kolumnami x_id
i y_id
, które razem tworzą klucz podstawowy dla łącza. Każdy X może być powiązany z wieloma Y i odwrotnie. To jest konfiguracja dla mojej istniejącej relacji wiele do wielu.
Podstawowa skrzynka
Teraz dodatkowo mam zestaw właściwości zdefiniowanych w innej tabeli oraz zestaw warunków, w których dana para (X, Y) powinna mieć właściwość P. Liczba warunków jest stała i taka sama dla wszystkich par. Mówią w zasadzie: „W sytuacji C1 para (X1, Y1) ma właściwość P1”, „W sytuacji C2 para (X1, Y1) ma właściwość P2” i tak dalej, dla trzech sytuacji / warunków dla każdej pary w złączeniu stół.
opcja 1
W mojej obecnej sytuacji istnieją dokładnie trzy takie warunki, a nie mam żadnego powodu, by oczekiwać, że w celu zwiększenia, więc jedną z możliwości jest dodanie kolumny c1_p_id
, c2_p_id
i c3_p_id
do featx_featy
, określając dla danego x_id
a y_id
, którego właściwość p_id
do stosowania w każdym z trzech przypadków .
Nie wydaje mi się to świetnym pomysłem, ponieważ komplikuje on SQL, aby wybrać wszystkie właściwości zastosowane do funkcji i nie łatwo skaluje się do większej liczby warunków. Wymusza jednak wymóg pewnej liczby warunków na parę (X, Y). W rzeczywistości jest to jedyna opcja, która to robi.
Opcja 2
Utwórz tabelę warunków cond
i dodaj identyfikator warunku do klucza podstawowego tabeli łączenia.
Jednym minusem tego jest to, że nie określa liczby warunków dla każdej pary. Innym jest to, że gdy rozważam tylko początkowy związek z czymś takim jak
SELECT objx.*, objy.* FROM objx
INNER JOIN objx_objy ON objx_objy.x_id = objx.id
INNER JOIN objy ON objy.id = objx_objy.y_id
Następnie muszę dodać DISTINCT
klauzulę, aby uniknąć powielania wpisów. Wydaje się, że stracił to fakt, że każda para powinna istnieć tylko raz.
Opcja 3
Utwórz nowy „identyfikator pary” w tabeli łączenia, a następnie umieść drugą tabelę łączy między pierwszą a właściwościami i warunkami.
Wydaje się, że ma to najmniej wad, oprócz braku wymuszania określonej liczby warunków dla każdej pary. Czy ma sens tworzenie nowego identyfikatora, który identyfikuje jedynie identyfikatory istniejące?
Opcja 4 (3b)
Zasadniczo to samo co opcja 3, ale bez tworzenia dodatkowego pola identyfikatora. Odbywa się to poprzez umieszczenie obu oryginalnych identyfikatorów w nowej tabeli łączenia, aby zawierała x_id
i y_id
pola zamiast xy_id
.
Dodatkową zaletą tego formularza jest to, że nie zmienia on istniejących tabel (choć nie są one jeszcze w produkcji). Jednak zasadniczo powiela całą tabelę wiele razy (lub tak też się wydaje), więc też nie wydaje się idealny.
streszczenie
Mam wrażenie, że opcje 3 i 4 są na tyle podobne, że mógłbym wybrać jedną z nich. Prawdopodobnie miałbym do tej pory, gdyby nie wymóg małej, stałej liczby linków do właściwości, co sprawia, że Opcja 1 wydaje się bardziej rozsądna niż byłaby w innym przypadku. Opierając się na niektórych bardzo ograniczonych testach, dodanie DISTINCT
klauzuli do moich zapytań nie wydaje się wpływać na wydajność w tej sytuacji, ale nie jestem pewien, czy Opcja 2 reprezentuje sytuację, podobnie jak inne, z powodu nieodłącznego duplikowania spowodowanego umieszczeniem te same pary (X, Y) w wielu wierszach tabeli łączy.
Czy jedna z tych opcji jest moim najlepszym rozwiązaniem, czy też jest inna struktura, którą powinienem rozważyć?
źródło
DISTINCT
klauzuli, myślałem o zapytaniu jak ten na koniec # 2, który linkix
iy
dziękixyc
ale nie odnosi się doc
... więc jeśli mam(x_id, y_id, c_id)
ograniczoneUNIQUE
z wierszy(1,1,1)
i(1,1,2)
, następnieSELECT x.id, y.id FROM x JOIN xyc JOIN y
, będę wracać dwóch identycznych wiersze(1,1)
i(1,1)
.Odpowiedzi:
opcja 1
Niekoniecznie komplikuje zapytania SQL (patrz wniosek poniżej).
Skaluje się z łatwością do większej liczby warunków, o ile nadal istnieje ustalona liczba warunków i nie ma ich dziesiątek ani setek.
Tak, i chociaż w komentarzu powiedziałeś, że jest to „najmniej ważne z moich wymagań”, nie powiedziałeś, że to w ogóle nie ma znaczenia.
Opcja 2Myślę, że możesz odrzucić tę opcję z powodu wspomnianych komplikacji.
objx_objy
Stół może być tabela jazdy dla niektórych zapytań (np „wybierz wszystkie właściwości zastosowane do funkcji”, który biorę na myśli wszystkie właściwości stosowane doobjx
lubobjy
). Możesz użyć widoku do wstępnego zastosowania,DISTINCT
więc nie jest to kwestia skomplikowanych zapytań, ale skaluje się to bardzo źle pod względem wydajności przy bardzo niewielkim zysku.Opcja 3Nie, nie ma - opcja 4 jest lepsza pod każdym względem.
Opcja 4
Ta opcja jest w porządku - jest to oczywisty sposób konfigurowania relacji, jeśli liczba właściwości jest zmienna lub może ulec zmianie
Wniosek
Moją preferencją byłaby opcja 1, jeśli liczba właściwości na
objx_objy
jest prawdopodobnie stabilna, i jeśli nie możesz sobie wyobrazić, aby kiedykolwiek dodać więcej niż garść dodatkowych. Jest to również jedyna opcja, która wymusza ograniczenie „liczba właściwości = 3” - wymuszenie podobnego ograniczenia w opcji 4 prawdopodobnie wymagałoby dodaniac1_p_id
… kolumn do tabeli xy *.Jeśli naprawdę nie dbasz o ten warunek, a także masz powody, by wątpić, że liczba właściwości będzie stabilna, wybierz opcję 4.
Jeśli nie masz pewności, wybierz opcję 1 - jest to prostsze i zdecydowanie lepsze, jeśli masz taką opcję, jak powiedzieli inni. W przypadku odłożenia opcji 1 „… ponieważ komplikowanie przez SQL wyboru wszystkich właściwości zastosowanych do funkcji…” sugeruję utworzenie widoku zapewniającego te same dane, co dodatkowa tabela w opcji 4:
tabele opcji 1:
zobacz opcję „emuluj” 4:
„wybierz wszystkie właściwości zastosowane do obiektu”:
dbfiddle tutaj
źródło
Wierzę, że każda z tych opcji mogłaby działać, ale wybrałbym opcję 1, jeśli liczba warunków jest naprawdę ustalona na 3, a opcję 2, jeśli tak nie jest. Brzytwa Ockhama działa również przy projektowaniu baz danych, przy czym wszystkie inne czynniki są równe, najprostszy projekt jest zwykle najlepszy.
Chociaż jeśli chcesz przestrzegać ścisłych zasad normalizacji bazy danych, uważam, że musisz wybrać 2, niezależnie od tego, czy liczba warunków jest ustalona.
źródło