Jestem w trakcie projektowania bazy danych i zastanawiam się nad moimi początkowymi decyzjami projektowymi ...
Typy produktów są następujące ... Modele, części, zestawy części zamiennych i opcje.
Opcja A (pierwszy projekt): planowałem mieć osobne tabele dla powyższych typów produktów. Powiedziałbym, że około 75% pól będzie takich samych w każdej tabeli.
Każdy typ produktu utworzyłem jako osobne tabele ze względu na powiązania, które muszę między nimi utworzyć. Na przykład model może mieć wiele opcji, a opcja może mieć wiele modeli. Opcja może również mieć wiele części, a część może mieć wiele opcji ... i tak dalej ...
Opcja B: Zamiast osobnych tabel mogłem stworzyć tabelę o nazwie Produkt, która obejmuje model, część, zestawy części zamiennych i opcje. Mógłbym mieć jedno pole o nazwie typ, aby rozróżnić model, opcje itp. Przypuszczam, że wadą jest to, że kilka pól nigdy nie będzie używanych (lewa null) dla niektórych typów produktów. Zgaduję, że w tym miejscu mogłyby się pojawić „nie najlepsze praktyki”.
Opcja B znacznie zmniejszyłaby złożoność projektu db. Nie musiałbym też martwić się o odniesienie do wielu tabel podczas pobierania danych do zapytań ...
Odpowiedzi:
Gdyby to była moja decyzja projektowa, prawdopodobnie wybrałbym więcej opcji „C” (zmodyfikowana opcja a).
Po pierwsze, dlaczego nie „Opcja B”:
Po pierwsze, podoba mi się przejrzystość, jaką zapewnia każdy produkt. Jeśli wszystko jest jednym dużym stołem z polem określającym typ, relacja nie jest tak wyraźna.
Po drugie, strategia indeksowania zawsze wymagałaby wyświetlenia tego pola typu. Ponieważ są to tylko 4 typy, liczność indeksu jest bardzo niska (w
SELECT * FROM product_table WHERE type='X'
zasadzie i tak wykonuje pełny skan tabeli)Opcja C
Minusem jest złożoność polegająca na unikaniu sierot, gdy rzeczy są aktualizowane / usuwane, oraz na wstępnym projektowaniu zapytań korzystających z tych tabel.
źródło
productID
byłby FK naproduct.id
ioptionID
jest FK naoption.id
. Właśnie to miałem na myśli przez tabelę linków. Tak, w tym projekcie konieczne jest, aby jeden produkt mógł łączyć się z wieloma opcjami.Proponuję zacząć od „poprawnego” modelu relacyjnego, twojej opcji A. Jeśli typowe użycie tego modelu prowadzi do denormalizacji w niektórych obszarach, nie bój się tego.
W zeszłym tygodniu dyskutowałem z kolegą, w jaki sposób projekty schematów są często uważane za coś, co jest osadzone w kamieniu i nigdy nie może się zmienić. Dziwne, biorąc pod uwagę, jak refaktoryzacja jest w praktyce akceptowana w każdej innej warstwie aplikacji, że refaktoryzacja schematu bazy danych jest nadal postrzegana jako niepraktyczna.
Jeśli interfejs do bazy danych jest dobrze zaprojektowany, nic nie stoi na przeszkodzie, aby dostosować schemat, gdy dowiesz się więcej o wzorcach użytkowania systemu.
źródło
Bardzo podobny do Brzmi listy materiałów / wielokrotne cardinalities heirarcy że Paul Nielsen opisuje w rozdziale 17 z SQL Server 2008 Biblii .
Cały rozdział to bardzo dobra lektura, a konkretny rozdział dotyczący twojego problemu wielu do wielu znajduje się na stronach 416-419.
To najlepsza dyskusja, jaką widziałem na temat projektowania danych części rozłożonej na części .
źródło
Jeśli potrafisz zobrazować prawdopodobny scenariusz, w którym często pojawiałyby się zapytania dotyczące wszystkich czterech typów produktów (i wydaje mi się to prawdopodobne), to Twoja opcja B jest najlepsza.
Zamiast pozostawiać wiele nieużywanych pól zerowalnych w tabeli Produkt, dlaczego nie dodać tabeli ModelProduct, tabeli PartProduct, tabeli ReplacementPartKitProduct i mieć w tych tabelach tylko pola odrębne dla tych typów? Użyj tego samego klucza podstawowego na tych tabelach, co tabela produktu. Dołącz do tabeli Product and ModelProduct, jeśli chcesz pracować z modelami. Chcesz ustalić, czy posiadany rekord produktu jest częścią? Po prostu wykonaj lewe sprzężenie z produktu na PartProduct, a jeśli PartProduct. [PrimaryKey] nie ma wartości zerowej, masz Part. Jeśli ma wartość null, nie jest częścią. Alternatywnie możesz dodać pole ProductType do tabeli Product.
źródło