pojedyncza tabela z dodatkowymi kolumnami vs wiele tabel, które duplikują schemat


13

Pracuję nad projektem, w którym w pewnym momencie musiałem podjąć decyzję, czy w bazie danych powinienem mieć jedną tabelę z wieloma kolumnami, z których nie korzysta każdy rekord, lub wiele tabel ze zduplikowanym schematem.

Tworzę aplikację sportową, która może obsługiwać wiele dyscyplin sportowych. Poradzimy sobie na przykład z NBA, NHL, MLB, NFL. Każdy sport ma bardzo podobne koncepcje - zespoły, harmonogramy, kontuzje, informacje o graczach ..

Nasze źródło danych oczywiście nie daje nam każdej części danych w tym samym schemacie. Każdy sport ma inny schemat, do którego otrzymujemy dane od naszego dostawcy.

Ponieważ nie było wystarczająco dużo czasu (żądania klientów), aby przeprowadzić analizę danych źródłowych w celu ustalenia podobieństw, zabezpieczyłem swój zakład i wziąłem „bezpieczny zakład” i utworzyłem osobne tabele dla każdego sportu zamiast jednego zestawu tabel, które wszystkie używany sport.

Wynikiem jest zduplikowany schemat w kilku tabelach, a więc także zduplikowane interfejsy do bazy danych (np. Przechowywane procy). Mam coś takiego jak NBA_Game, NFL_Game, NBA_Team, NFL_Team itp. Każda tabela może mieć kilka właściwości, których nie ma druga, i kilka wspólnych. mówi się o 5-10 stołach w 4 lub 5 dyscyplinach sportowych. Nadal nie jestem pewien, czy jest to całkowicie zła rzecz - alternatywa, mając jeden zestaw stolików, który miał właściwości, z których nie skorzystałyby wszystkie sporty, mogłaby sama w sobie być niewygodna.

Czy ktoś, kto to zrobił, wpadł w pułapki tego rodzaju projektów i mógłby się tutaj podzielić swoimi doświadczeniami? Rzeczy, które mogą pomóc mi wiedzieć teraz zamiast uczyć się trudnej drogi? Czy zrobiłeś to w drugą stronę, mając jeden duży stół / zestaw tabel, z kolumnami, których nie używałby każdy rekord? Na jakie pułapki wpadłeś, robiąc to?

Czy istnieje jakaś alternatywa, taka jak dziedziczenie tabeli , z której korzystałeś w przeszłości, która działała lepiej?

Dzięki

Odpowiedzi:


12

Ostatecznie sprowadza się to do zastosowania i architektury.

Architektura

Czy system obsługuje „jakikolwiek sport”? Czy pomysł, który postawiłeś na czapkę astronautów architektury i zbudowałeś ogólny system, który poradzi sobie z każdym rodzajem sportu, który dziś może nawet nie istnieć?

Jeśli tak, to oczywiście posiadanie dynamicznie nazwanych tabel jest ogromnym problemem, więc sensownie byłoby mieć schemat, który obsługuje n sportu, jeśli jest to wymagane.

To powiedziawszy, mam bardzo silną stronniczość wobec tego podejścia: prawie zawsze jest to więcej pracy i prowadzi do gorszych wyników. Utworzenie osobnego interfejsu użytkownika, schematu itp. Dla każdej dyscypliny sportowej ostatecznie zapewni lepszą obsługę i łatwiejszy do utrzymania kod, nawet jeśli oznacza to powierzchowne powielanie (jak uniknąć / zminimalizować to osobne pytanie).

Jak radzisz sobie z graczami uprawiającymi wiele dyscyplin sportowych? Czy dostają dwa wpisy (np. Traktujesz jak różnych ludzi) czy próbujesz zrobić z nimi coś konkretnego?

Posługiwać się

Załóżmy więc, że nie uprawiasz sportu dynamicznie (np. Jeśli ktoś chce dodać nowy sport, wymaga wysiłku rozwojowego, aby go dodać).

Czy zdarza się kiedyś, że wyświetlasz graczy (lub inny przedmiot, o którym wspominałeś) z więcej niż jednego sportu na raz?

Widziałem to dla funkcji wyszukiwania, w której można wyszukiwać według nazwy zawodnika lub drużyny (niezależnie od sportu), ale poza tym nie wyobrażam sobie wielu przypadków użycia.

Jeśli nigdy nie musisz tego robić, twoje podejście jest całkowicie w porządku. Możesz przestać czytać tutaj.

Alternatywne schematy

Wyświetlenia

Jestem fanem KISS. W ciągu ponad 15 lat rozwoju oprogramowania wciąż powracam do filozofii „buduj najprostsze rzeczy, które działają”.

Więc moją pierwszą reakcją, zakładając, że funkcja wyszukiwania między sportami jest naprawdę jedynym przypadkiem użycia, jest tworzenie widoków:

SELECT PlayerName, 'NFL' as [Sport], TeamName FROM NFL_Players JOIN NFL_Teams ... 
UNION  
SELECT PlayerName, 'NHL' as [Sport], TeamName FROM NHL_Players JOIN NHL_Teams ... 
UNION ....

Oczywiście, jeśli dodasz nowy sport, musisz dodać do widoku. Przydatne może być również dołączenie innych typowych informacji, ale tak naprawdę zależy to od tego, co trzeba pokazać.

Staram się zachować wszystkie elementy związane ze sportem w definicji widoku, aby kod wyszukiwania nie musiał zawierać zbyt wiele lub żadnego określonego kodu (oprócz być może wiedzy o tym, jak utworzyć link do /nhl/players/player-namevs /nfl/...lub jak robi to Twoja aplikacja).

Dziedziczenie tabeli

Dziedziczenie tabeli może działać, ale jest dość złożone. Nie mam z tym dużego doświadczenia i wydaje mi się, że za każdym razem, gdy brałem udział w ocenie, robiliśmy coś prostszego (jak sugeruję tutaj).

Więc osobiście nie wiem, dlaczego to byłoby przydatne, ale może istnieje przekonujący przypadek użycia (o którym nie wiem), który uzasadnia złożoność (np. Dziedziczenie tabeli rozwiązuje przypadek użycia lepiej niż jakiekolwiek inne rozwiązanie) .

Oddzielne tabele dla atrybutów specyficznych dla sportu

Możesz zrobić pojedynczy playersstół, który ma atrybuty wspólne dla wszystkich graczy ze wszystkich dyscyplin sportowych, a następnie inny zestaw takich tabel nhl_players_detailszawiera identyfikator gracza i kolumny z dodatkowymi informacjami na temat gracza. Jeśli istnieje wiele typowych atrybutów lub masz wiele zastosowań „wszystkich graczy ze wszystkich dyscyplin sportowych”, może to mieć sens.

Pary kluczowych wartości dla atrybutów specyficznych dla sportu

Całkowicie alternatywne podejście: posiada playersstół (ponownie, z parametrów takich jak nazwa), a następnie player_datatabeli, która ma PlayerId, Sport, Attribute, Value. Wprowadzone nazwy atrybutów będą specyficzne dla sportu. Pozwala to zasadniczo dodawać nowe atrybuty bez modyfikowania schematu (kod nadal musiałby wiedzieć, aby je załadować / wyświetlić). Wadą jest utrata pewnej integralności: wartość zwykle byłaby polem łańcuchowym, więc kod aplikacji musiałby być odporny i obsługiwać potencjalne niepowodzenia konwersji łańcucha valuena określony typ danych (np. Liczbę całkowitą).

Ta koncepcja może oczywiście dotyczyć drużyn, gier itp.


Poszukiwanie rozwiązania starszego projektu pozwoli na uzyskanie wielu autentycznych typów i tabel, wzmianka o widokach tutaj, o których zapomniałem, naprawdę pomogła zaoferować inne możliwe rozwiązanie moich badań. Dziękuję Ci.
FullStackFool

5

Mówisz o normalizacji bazy danych . Możesz odczuwać ulgę, gdy dowiadujesz się, że nie ma czegoś takiego jak idealny model danych i że większa normalizacja nie zawsze jest lepsza. Normalizacja może nakładać koszty pod względem przejrzystości modelu danych i wydajności bazy danych. Dlatego wybór najlepszego modelu zależy od wymagań użytkowania.

Na pierwszy rzut oka twoje przykłady wydają się wystarczająco podobne w koncepcji (X_Game vs Y_Game i X_Team vs Y_Team), że dodatkowy narzut kilku kolumn nie wydaje się nieracjonalny. To powiedziawszy, jeśli każdy sport doda kilkadziesiąt dodatkowych kolumn do stołu, byłoby to rzeczywiście niewygodne.

W takim przypadku możesz rozważyć model hybrydowy, w którym wspólne dane są przechowywane w centralnej tabeli, ale dane specyficzne dla sportu są przechowywane w powiązanej strukturze danych. Coś jak:

table Game {
    gameId int,
    teamId1 int fk,
    teamId2 int fk
}

table HockeyGame {
    gameId int fk,
    penaltyMinutes int
}

table BasketballGame {
    gameId int fk,
    freeThrows int
}

To właśnie zamierzałem zaproponować, a może kolumna w tabeli gier wskazująca typ gry. Zdaję sobie sprawę, że można to wywnioskować, dołączając do innych stołów, ale jeśli liczba rodzajów gier rośnie, zaczyna to być nużące.
Rory Hunter

Oczywiście - to tylko szkielet modelu ilustrujący podstawowe relacje i kilka przykładów tego, co może być wspólnymi danymi w porównaniu do danych specyficznych dla sportu.
Midnotion
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.