Istnieją dwie tabele: Deal
i DealCategories
. Jedna umowa może mieć wiele kategorii transakcji.
Zatem właściwym sposobem powinno być utworzenie tabeli DealCategories
o następującej strukturze:
DealCategoryId (PK)
DealId (FK)
DealCategoryId (FK)
Jednak nasz zespół outsourcingowy zapisał w Deal
tabeli wiele kategorii w ten sposób:
DealId (PK)
DealCategory -- In here they store multiple deal ids separated by commas like this: 18,25,32.
Uważam, że to, co zrobili, jest złe, ale nie wiem, jak jasno wyjaśnić, dlaczego tak nie jest.
Jak mam im wyjaśnić, że to źle? A może to ja się mylę, a to jest do przyjęcia?
database-design
foreign-key
Sarawut Positwinyu
źródło
źródło
Odpowiedzi:
Tak, to okropny pomysł.
Zamiast iść:
Teraz musisz iść:
Następnie musisz wykonać czynności w kodzie aplikacji, aby podzielić listę przecinków na poszczególne liczby, a następnie osobno przeszukać bazę danych:
Ten projekt antipattern wynika albo z całkowitego niezrozumienia modelowania relacyjnego (nie musisz bać się tabel. Tabele to twoi znajomi. Używaj ich), albo dziwnie błędnego przekonania, że szybciej jest wziąć listę oddzieloną przecinkami i podzielić ją w kodzie aplikacji niż po to, aby dodać tabelę linków ( nigdy nie jest). Trzecią opcją jest to, że nie są wystarczająco pewni / kompetentni w SQL, aby móc konfigurować klucze obce, ale w takim przypadku nie powinni mieć nic wspólnego z projektowaniem modelu relacyjnego.
SQL Antipatterns (Karwin, 2010) poświęca cały rozdział temu antypatternowi (który nazywa „Jaywalking”), strony 15-23. Ponadto autor opublikował podobne pytanie w SO . Kluczowe punkty, które zauważa (w odniesieniu do tego przykładu) to:
COUNT
,SUM
etc), ponownie, różnią się od „skomplikowane” do „prawie niemożliwe”. Zapytaj programistów, jak uzyskają listę wszystkich kategorii wraz z liczbą ofert w tej kategorii. Przy odpowiednim projekcie są to cztery linie SQL.VARCHAR
ograniczenia długości listy. Chociaż jeśli masz listę oddzieloną przecinkami, która zawiera ponad 4000 znaków, istnieje szansa, że potwór i tak będzie powolny jak diabli.TLDR: Jest to zasadniczo wadliwy projekt, nie skaluje się dobrze, wprowadza dodatkową złożoność nawet najprostszych zapytań, a zaraz po wyjęciu z pudełka spowalnia działanie aplikacji.
źródło
To naprawdę dobry projekt, jeśli potrzebujesz tylko zapytać o kategorie dla danej oferty.
Ale to okropne, jeśli chcesz poznać wszystkie oferty w danej kategorii.
Utrudnia to także wykonywanie innych czynności, takich jak aktualizacje, zliczanie, dołączanie itp.
Denormalizacja ma swoje miejsce, ale należy pamiętać, że optymalizuje ona jeden typ zapytania, kosztem wszystkich innych, które możesz wykonać w stosunku do tych samych danych. Jeśli wiesz, że zawsze będziesz sprawdzać według jednego wzorca, może to dać przewagę w użyciu zdormalizowanego projektu. Ale jeśli istnieje jakakolwiek szansa, że możesz potrzebować większej elastyczności w typach zapytań, trzymaj się znormalizowanego projektu.
Jak każda inna forma optymalizacji, musisz wiedzieć, jakie zapytania będziesz uruchamiać, zanim zdecydujesz, czy denormalizacja jest uzasadniona.
źródło
select * from DealCategories where DealId in (1,2,3,4,...)
. Masz więcej doświadczenia, jeśli chodzi o projektowanie baz danych, niż ja, więc może masz uzasadniony powód, by tak „ekstremalnie dostroić” w bardzo szczególnych przypadkach. Moim jedynym pomysłem, aby to uzasadnić, jest bardzo dużeselect
obciążenie Deal / DealCategory. To mi przypomina zespół outsourcingu bez wiedzy na temat projektowania baz danych, poza tworzeniem tabel, stworzeniem.Wiele wartości w kolumnie jest przeciwnych pierwszej formie normalnej.
Nie ma też absolutnie żadnego wzrostu prędkości, ponieważ tabele mają być połączone w bazie danych. Najpierw musisz przeczytać i przeanalizować ciąg, a następnie wybrać wszystkie kategorie dla „Oferty”.
Poprawną implementacją byłaby tabela połączeń, taka jak „DealDealCategories”, z DealId i DealCategoryId.
Zła implementacja hierarchii?
Ponadto FK w DealCategory do innej DealCategory wygląda jak zła implementacja hierarchii / drzewa DealCategory. Praca z drzewami za pośrednictwem relacji nadrzędnego identyfikatora (tzw. Listy sąsiedztwa) jest uciążliwa!
Sprawdź zestawy zagnieżdżone (dobre do odczytania, ale trudne do modyfikacji) i tabele zamknięcia (najlepsza ogólna wydajność, ale możliwe wysokie zużycie pamięci - prawdopodobnie nie za dużo dla Twoich DealCategory) podczas wdrażania hierarchii!
źródło