Czy utworzyć osobne tabele dla różnych typów produktów?

25

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ń ...

payling
źródło
2
W tym punkcie sugeruję tworzenie arkuszy kalkulacyjnych, które naśladują układ tabeli i wypełniają je danymi. Ujawni to wszelkie istniejące słabości.
Michael Riley - AKA Gunny
Jak wskażesz klucze obce na różne produkty, jeśli znajdują się w różnych tabelach? Proszę przeczytać o dziedziczeniu tabeli.
Neil McGuigan

Odpowiedzi:

8

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

  • Utwórz tabelę nadrzędną, która zawiera tylko kolumny współużytkowane przez wszystkie typy
  • Utwórz każdy typ produktu jako własną tabelę z osobnymi kolumnami, z jedną dodatkową: Link do tabeli nadrzędnej
  • Utwórz każdą tabelę „linków”: Product_Option, Model_option itp. Z linkami do odpowiednich kluczy.
  • Dla osób z wzajemnymi linkami (MODEL_OPTION, OPTION_MODEL) idź dalej i utwórz te tabele. To doda przejrzystości twoich połączeń dla każdego, kto na to spojrzy.

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.

Derek Downey
źródło
5
Są teraz tylko 4 typy, ale co, jeśli później zostaną dodane więcej? Jestem pewien, że główna tabela produktów Amazon nosiła pierwotnie nazwę „Książki”, ale czy uważasz, że teraz mają one osobną tabelę dla każdego rodzaju produktu? Nie sądzę, że każdy typ powinien mieć własną tabelę, ale możesz użyć modelu EAV dla dodatkowych właściwości, które każdy typ może mieć wspólną.
Aaron Bertrand
1
@Aaron Uczciwy punkt na temat przyszłego wzrostu rodzajów produktów. Gdyby ten scenariusz mógł rozszerzyć się na ponad 10 rodzajów produktów, ponownie rozważyłbym. Ale wydaje mi się, że określone tabele produktów to dobry wybór dla niewielkiej liczby rodzajów produktów.
Derek Downey
1
Opcja C: Czy potrzebna jest tabela łączy? Wyobrażam sobie, że PK Product_Option będzie pasowało do PK tabeli Product, a to stworzy powiązanie łączące obie tabele.
payling
Używając opcji Product_option jako przykładu, schemat byłby (moim zdaniem): id, productID, optionID. productIDbyłby FK na product.idi optionIDjest FK na option.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.
Derek Downey
Dobrze, rozumiem. Źle odczytałem to, co wpisałeś ... Ups.
payling
7

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.

Mark Storey-Smith
źródło
2

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 .

Michael Riley - AKA Gunny
źródło
To rozwiązanie wygląda podobnie do opcji B (jeśli dobrze to rozumiem, czego nie jestem pewien). Chciałbym mieć tabelę główną (Produkty) i tabelę „linków” (zwaną także tabelą sąsiadującą / BillsofMaterials), aby utworzyć powiązania między modelami, opcjami, zestawami itp. Czy to prawda?
payling
Myślę, że problem jest zmącony z powodu opcji. Pozwala na chwilę usunąć opcje z dyskusji. Części są najmniejszą jednostką. Grupa części tworzy model. Grupa części zamiennych w postaci zestawu stanowi podzbiór modelu. Jak na razie dobrze. Teraz części mają opcje, dla uproszczenia załóżmy, że obejmuje to dwie kategorie kolor (czarny, czerwony, chrom) i materiał (metal, drewno, tworzywo sztuczne). Wspomniałeś również, że modele mają opcje. Czy opcje modelu są oddzielone od opcji części, czy też modele wydają się mieć tylko opcje, ponieważ części sprawiają, że modele są inne?
Michael Riley - AKA Gunny
Części nie mają „opcji” w moim projekcie. Definiuję opcję jako coś, co pasuje do modelu, który zapewnia jej rozszerzoną funkcjonalność. Opcja składa się z części. Model może mieć wiele różnych opcji. Opcja może pasować także do wielu różnych modeli.
payling
Nie tak sformułowałeś swoje pytanie. Cytat: „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 ...” W tym punkcie sugeruję ci utwórz arkusze kalkulacyjne naśladujące układ tabeli i wypełnij je danymi. Ujawni to wszelkie istniejące słabości.
Michael Riley - AKA Gunny
0

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.

Alan McBee
źródło
Pola zerowe byłyby minimalne, ponieważ około 75% pól byłoby używanych w każdej tabeli. Chyba bardziej martwię się o relacje między rodzajami produktów. Będę miał około trzech tabel linków wskazujących na ten sam stół. Model_has_Option dwa klucze podstawowe, oba identyfikatory produktu w tabeli produktów, gdybym używał tylko jednej tabeli do reprezentowania typów produktów. Bardziej martwię się, czy to jest właściwe, czy nie.
payling 27.07.2011
Chociaż na „właściwą” decyzję wpływa wiele czynników, należy wziąć pod uwagę dwa ogólne czynniki. 1: ogólne wymagania dotyczące wydajności; 2: adaptowalność / złożoność / łatwość konserwacji. Jeden z tych dwóch prawdopodobnie jest nieco ważniejszy od drugiego. Jeśli potrzebujesz prędkości, zdenormalizuj, pozostając w opcji A. Będziesz miał powielanie; to jest oczekiwane. Jeśli musisz regularnie manipulować schematem, a szybkość nie jest najważniejszym czynnikiem, wtedy opcja B. Otrzymujesz go „dobrze”, znając swoje priorytety, a nie przestrzegając „najlepszych praktyk innych”.
Alan McBee