Istnieje wiele powodów, dla których używanie jednego dużego „stołu bożego” jest złe. Spróbuję zilustrować problemy z utworzoną przykładową bazą danych. Załóżmy, że próbujesz modelować wydarzenia sportowe. Powiemy, że chcesz modelować gry i drużyny grające w te gry. Projekt z wieloma tabelami może wyglądać tak (celowo jest to bardzo uproszczone, więc nie daj się złapać w miejscach, w których można zastosować większą normalizację):
Teams
Id | Name | HomeCity
Games
Id | StartsAt | HomeTeamId | AwayTeamId | Location
i baza danych z pojedynczą tabelą wyglądałaby tak
TeamsAndGames
Id | TeamName | TeamHomeCity | GameStartsAt | GameHomeTeamId | GameAwayTeamId | Location
Najpierw spójrzmy na tworzenie indeksów na tych tabelach. Gdybym potrzebował indeksu dla rodzinnego miasta dla drużyny, mógłbym dość łatwo dodać go do Teams
stołu lub TeamsAndGames
stołu. Pamiętaj, że za każdym razem, gdy tworzysz indeks, musi on być gdzieś przechowywany na dysku i aktualizowany w miarę dodawania wierszy do tabeli. W przypadku Teams
stołu jest to dość proste. Wprowadziłem nowy zespół, baza danych aktualizuje indeks. Ale po co TeamsAndGames
? To samo odnosi się doTeams
przykład. Dodam zespół, indeks się aktualizuje. Ale dzieje się tak również, gdy dodam grę! Mimo że to pole będzie puste dla gry, indeks i tak musi zostać zaktualizowany i zapisany na dysku dla tej gry. Dla jednego indeksu nie brzmi to tak źle. Ale kiedy potrzebujesz wielu indeksów dla wielu jednostek wciśniętych w tę tabelę, marnujesz dużo miejsca na przechowywanie indeksów i mnóstwo czasu procesora na ich aktualizowanie pod kątem rzeczy, których nie dotyczą.
Po drugie, spójność danych. W przypadku korzystania z dwóch oddzielnych stołów, mogę używać kluczy obcych ze Games
stołu do Teams
stołu, aby określić, które drużyny grają w grę. Zakładając, że nie dopuszczam do zerowania kolumn HomeTeamId
i AwayTeamId
, baza danych zapewni, że w każdej grze, w której będę grał, będą 2 drużyny i że te drużyny będą istnieć w mojej bazie danych. Ale co ze scenariuszem pojedynczego stołu? Ponieważ w tej tabeli znajduje się wiele elementów, kolumny te powinny być zerowalne (możesz sprawić, że nie będą zerowalne i wrzuć tam śmieci, ale to tylko okropny pomysł). Jeśli te kolumny są zerowalne, baza danych nie może już zagwarantować, że po wstawieniu gry będą miały dwie drużyny.
Ale co jeśli zdecydujesz się po prostu i tak na to? Skonfiguruj klucze obce w taki sposób, aby pola te wskazywały na inny element w tej samej tabeli. Ale teraz baza danych po prostu upewni się, że te jednostki istnieją w tabeli, a nie, że są one poprawnego typu. Możesz bardzo łatwo ustawić GameHomeTeamId
identyfikator innej gry, a baza danych w ogóle nie będzie narzekać. Jeśli spróbujesz tego w scenariuszu z wieloma tabelami, baza danych będzie pasować.
Możesz spróbować złagodzić te problemy, mówiąc „cóż, upewnimy się, że nigdy nie zrobimy tego w kodzie”. Jeśli masz pewność, że umiesz pisać kod wolny od błędów po raz pierwszy i że możesz wziąć pod uwagę każdą dziwną kombinację rzeczy, które użytkownik może wypróbować, śmiało. Osobiście nie jestem pewien swojej zdolności do robienia tych rzeczy, więc pozwolę, aby baza danych dała mi dodatkową siatkę bezpieczeństwa.
(Jest jeszcze gorzej, jeśli Twój projekt polega na kopiowaniu wszystkich istotnych danych między wierszami zamiast korzystania z kluczy obcych. Wszelkie niespójności w pisowni / innych danych będą trudne do rozwiązania. Jak rozpoznać, czy „Jon” jest błędem w pisowni „John” „lub jeśli było to zamierzone (ponieważ są to dwie osobne osoby)?)
Po trzecie, prawie każda kolumna musi mieć wartość zerową lub być wypełniona albo skopiowanymi, albo śmieciowymi danymi. Gra nie potrzebuje TeamName
lub TeamHomeCity
. Tak więc albo każda gra potrzebuje jakiegoś symbolu zastępczego, albo musi być zerowa. A jeśli jest zerowalne, baza danych chętnie wybierze grę bez TeamName
. Zajmie to również zespół bez nazwy, nawet jeśli logika biznesowa mówi, że to nigdy nie powinno się zdarzyć.
Istnieje kilka innych powodów, dla których chciałbyś mieć osobne tabele (w tym zachowanie rozsądku programisty). Istnieje nawet kilka powodów, dla których większy stół może być lepszy (denormalizacja czasami poprawia wydajność). Te scenariusze są nieliczne i dalekie od (i zwykle najlepiej sobie z nimi radzić, gdy masz wskaźniki wydajności, które pokazują, że to naprawdę jest problem, a nie brakujący indeks lub coś innego).
Wreszcie opracuj coś, co będzie łatwe w utrzymaniu. To, że „działa”, nie oznacza, że jest OK. Próba utrzymywania boskich tabel (takich jak boskie klasy) to koszmar. Po prostu szykujesz się na ból później.