Profesor kazał nam przechowywać zserializowane obiekty Java jako obiekty BLOB zamiast definiować tabele relacyjne

21

Zamiast faktycznie definiować tabele z poprawnymi atrybutami, mój profesor powiedział nam, że możemy mapować obiekty na identyfikatory takie jak to:

id (int)  |   Serialized Object (blob)
   1               10010110110

Widzę w tym tyle problemów; nadmiarowość danych, osobne śledzenie identyfikatorów, wciągnięcie całej tabeli do pamięci w celu wyszukania czegokolwiek i ** jeśli chcę zmienić model w kodzie Java, nie będę już mógł deserializować obiektu blob przechowywanego w baza danych do tego modelu.

Albo utknąłem na zawsze z tym modelem, albo muszę zrobić coś naprawdę brzydkiego, aby zmienić mój model. ** To wszystko wydaje mi się złą formą. Czy mam uzasadnienie, że nie zgadzam się z moim profesorem? Czy jest z tego jakaś korzyść, o której nie myślałem? Jeśli mam rację, czy powinienem coś powiedzieć o tym profesorowi? Głosił to całej mojej klasie, a nawet powiedział, że zbudował projekty w ten sposób. Druga opinia byłaby świetna.

Kurs nosi nazwę Software Design .

Mój profesor nie powiedział, że to najlepszy sposób, ale powiedział, że jest to uzasadniona alternatywa dla definiowania tabel relacyjnych.

Model nie jest w żaden sposób dynamiczny.

Tyler Davis
źródło
Komentarze nie są przeznaczone do rozszerzonej dyskusji; ta rozmowa została przeniesiona do czatu .
Paul White mówi GoFundMonica

Odpowiedzi:

34
  1. To nie jest samo w sobie złe. Kłócenie się o „co jest lepsze” bez odpowiedniego kontekstu (= dokładne wymagania) jest ćwiczeniem daremnym.

  2. Pogrubiona część jest niepoprawna. Możesz z łatwością rozszerzyć obiekty już zserializowane, aby dodać nowe pola i osiągnąć pełną zgodność binarną ze starszymi obiektami. Możesz także po prostu tworzyć nowe klasy zamiast zmieniać oryginalne.

Twoja dyskusja z profesorem powinna koncentrować się na zaletach i wadach „relacyjnego” kontra „magazynu kluczowych wartości” w różnych scenariuszach, a nie na abstrakcyjnej „lepszości”. Możesz też porozmawiać o tym, czy Boże Narodzenie jest lepsze od Święta Dziękczynienia.

- edycja, po przeczytaniu innych odpowiedzi.

Jedna z pozostałych odpowiedzi mówi o tym, że „trudno jest wyobrazić sobie przypadek, w którym profesjonaliści przeważają nad wadami”.

Ponieważ cała dyskusja musi dotyczyć konkretnych problemów (w przeciwnym razie nie możemy nawet zdefiniować „lepszych” i „gorszych”), pozwólcie, że podam jeden konkretny przykład. Jest całkowicie wymyślony, ale starałem się przedstawić jak najwięcej szczegółów.

Wyobraź sobie, że masz witrynę z grami online z bazą danych, która przechowuje statystyki graczy w różnych grach online (granych w przeglądarce, zapisywanych w GWT i kompilowanych krzyżowo do javascript). Niektóre gry są strategiczne, niektóre są grami akcji, niektóre są platformówkami. Baza danych jest relacyjna i przechowuje graczy oraz historię rozgrywek i wynik.

Pewnego dnia otrzymasz dodatkowy wymóg: pozwól graczom zapisać stan gry w chmurze podczas gry, aby mogli ponownie uruchomić grę później, w tym samym momencie. Nie trzeba dodawać, że jedynym powodem do przechowywania tego stanu tymczasowego jest powrót do gry, sam stan nigdy nie będzie introspekcji.

Teraz masz dwie podstawowe opcje:

  • ponieważ gry są napisane w Javie, możesz dość łatwo pobrać model, wysłać go na serwer, serializować w jednym wierszu kodu i przechowywać jako obiekt blob. Stół będzie się nazywał „zapisane_gry” i będzie zawierał obce klucze do gracza i tak dalej. Z punktu widzenia bazy danych „gra zapisu” jest nieprzezroczystą, niepodzielną kroplą.

  • możesz utworzyć osobny model relacyjny dla każdej ze 100 gier (będą to dziesiątki stołów na grę). Na przykład dla samego Pacmana będziesz musiał mieć tabelę przechowującą pozycje wszystkich niezjedzonych granulek, bonusów, pozycji i aktualnego stanu duchów. Jeśli ktoś kiedyś zmodyfikuje grę, nawet nieznacznie, będziesz musiał zaktualizować model relacyjny. Ponadto dla każdego rodzaju gry konieczne będzie zaimplementowanie logiki zapisu modelu Java do bazy danych i jego ponownego odczytania.

Odpowiedź Justina Cave'a mówi, że powinieneś wybrać drugą opcję. Myślę, że to byłby ogromny błąd.

Mam przeczucie, że postrzeganie Justina Cave'a polega na tym, że to, co przedstawiłem powyżej, jest przypadkiem „przewrotnym” lub „rzadkim”. Uważam, że jeśli nie będzie w stanie przedstawić pewnego rodzaju twardych danych (na podstawie reprezentatywnego próbkowania wszystkich projektów IT na świecie, a nie tylko, powiedzmy, aplikacji korporacyjnych w USA), uważam taką opinię za klasyczny przypadek projekcji stronniczość.

W rzeczywistości problem serializowanych obiektów Java w relacyjnej bazie danych jest o wiele głębszy, niż się wydaje. Dotyka samego rdzenia 1NF, a mianowicie, co jest domeną atrybutu? . Jeśli naprawdę interesujesz się tym tematem, znajdziesz świetny artykuł autorstwa CJ Date, w jego Dacie na bazie danych: Pisma 2000-2006 .

fdreger
źródło
Komentarze nie są przeznaczone do rozszerzonej dyskusji; ta rozmowa została przeniesiona do czatu .
Paul White mówi GoFundMonica
22

Czy (i czy) ludzie mogą z powodzeniem realizować projekty, które robią tego rodzaju rzeczy? Niestety tak, robią to dość często.

Czy to dobre podejście? Nie, nie jest. Zasadniczo bierzesz stosunkowo drogą bazę danych i zamieniasz ją w stosunkowo wolny system plików. Jeśli naprawdę chcesz zbudować system, który zapisuje swój stan poprzez serializowanie i usuwanie serializacji obiektów, równie dobrze możesz użyć systemu plików zamiast bazy danych.

Jeśli budujesz systemy przechowujące dane poprzez serializację obiektów do bazy danych, nie zaprzyjaźnisz się z DBA. W końcu będziesz przechowywać zbędne dane. Otrzymasz strasznie niespójne dane - za każdym razem, gdy udostępniane dane są aktualizowane, niektóre obiekty kończą się nowymi wartościami, a niektóre kończą starymi wartościami. Uniemożliwisz jakiekolwiek raportowanie danych - wszystko, co każdy chce zrobić z danymi, będzie wymagało napisania dodatkowego kodu. To ogromny, ogromny problem w większości przedsiębiorstw, ponieważ chcą robić takie rzeczy, jak wyodrębnianie danych z jednego systemu w celu załadowania do innego systemu lub mieć system raportowania, który może dostarczać raporty z wielu aplikacji typu front-end. Ponadto, jak zauważyłeś, ciągle będziesz musiał radzić sobie z problemami, gdy „

Czy takie podejście ma zalety? Wydaje mi się, że można argumentować, że wdrożenie pierwszej wersji aplikacji jest dość łatwe. Pozwala to deweloperowi całkowicie zignorować wszystko, co jest związane z właściwą interakcją z bazą danych. Trudno mi wyobrazić sobie wiele przypadków, w których te zalety przeważają nad wieloma wadami tego podejścia.

Jeśli chodzi o sposób radzenia sobie z tym konkretnym profesorem, jest to osobny problem (i taki, który prawdopodobnie nie wchodzi w zakres tego forum). Jeśli twój profesor aktywnie rozwija projekty w prawdziwym świecie, prawdopodobnie nie będzie on bardzo otwarty na jakiekolwiek argumenty studenta, że ​​jego podejście jest zasadniczo złe (nawet jeśli podejście jest naprawdę złe). Lepiej ci będzie, jeśli wykonasz projekt tak, jak chce profesor, i nauczysz się, jak samodzielnie zapisywać dane (lub w innym kursie).

Justin Cave
źródło
2
To, co powiedziałeś, plus moje dwa centy. Wielokrotnego użytku dotyczy modułowości i udostępniania. Model obiektowy koncentruje się na udostępnianiu obiektów i ponownym wykorzystaniu kodu. Model bazy danych koncentruje się na udostępnianiu i ponownym wykorzystywaniu danych. Żaden model nie jest całkowicie kretyński. Żaden model nie jest perfekcyjny. I bardzo, bardzo trudne jest pogodzenie tych dwóch.
Walter Mitty
1
Zgadzam się z tym, ale nienawidzę patrzeć, jak profesor czegoś uczy i mówi, że jest to lepszy sposób bez konfrontacji. A co z pozostałymi biednymi studentami, którzy pójdą do prawdziwego świata, sądząc, że to właściwa droga?
Kevin
Pewnie. Ta formuła sprowadza się do obiektów udających dane. I są to dane, ale niezbyt przydatne dane.
Walter Mitty
Zaleta jest prawie zawsze usuwana, gdy tylko chcesz wydać wersję 2 swojej aplikacji.
Andy,
10

Są sytuacje, w których tego rodzaju projektowanie jest rozsądne, bez opisu twoich projektów i sposobu ich wykorzystania trudno jest powiedzieć, czy jest to właściwe, czy nie.

Twój DBA może cię nienawidzić, jeśli przechowujesz BLOBy, ale w wielu sytuacjach jedyną alternatywą jest przekształcenie tabel w wartość atrybutu Entity, która zyskuje jeszcze więcej nienawiści z DBA. Inną alternatywą jest użycie nierelacyjnych baz danych, zwykle bazujących na obiektach lub słownikach lub baz danych zorientowanych na dokumenty, których niektóre DBA, szczególnie te, które znają relacyjne, nienawidziłyby z jeszcze większą pasją. Nierelacyjna baza danych ma jednak swoje własne problemy, z pewnością może się zdarzyć, że użycie obiektowej bazy danych do przechowywania obiektów może ujawnić inne problemy, które można by łatwo rozwiązać w systemach relacyjnych.

Czy jest z tego jakaś korzyść, o której nie myślałem?

Przechowywanie zserializowanego obiektu oznacza, że ​​możesz przechowywać dane bez schematu (zwróć uwagę, że pomimo nazwy, schemat nie zwykle oznacza, że ​​w ogóle nie ma schematu, ale jest tylko schemat domyślny). Istnieje wiele domen problemowych, w których nie można zdefiniować schematu z wyprzedzeniem w czasie programowania, a stosowanie tradycyjnego projektu relacyjnej bazy danych oznaczałoby konieczność zmiany schematu bazy danych co drugi tydzień lub utworzenie tabeli zawierającej 80% nieużywanych kolumn w 80% przypadków lub setki różnych tabel do przechowywania tych samych danych, z których żadna nie wskazuje na dobry projekt. Przyczyną tego problemu jest zazwyczaj wymuszenie dopasowania nierelacyjnej domeny problemowej do relacyjnej bazy danych.

Oczywiście istnieje wiele projektów, w których ludzie myślą, że muszą używać EAV, schematów lub sklepu z kroplami, co okazuje się niepotrzebnie powodować ból, którego można byłoby uniknąć. Zdecydowanie powinieneś omówić ze swoim profesorem, jakie jest jego rozumowanie i przedstawić własne argumenty; słuchajcie argumentów i bądźcie gotowi, że w końcu się z nim zgodzicie, albo nie, może się myli.

Lie Ryan
źródło
7

Zrobiłem to już wcześniej - jest to przydatna technika w niektórych scenariuszach, jednak zależy to od zastosowanego formatu serializacji. Jeśli to zrobię, upewnię się, że używam formatu serializacji, który pozwala mi na usunięcie z szeregów starszych wersji mojego modelu (np. XML).

Zwykle używałbym tego w scenariuszach, w których format danych spowodowałby skomplikowany model relacyjny, który nie oferuje żadnych korzyści (np. Gdy wymagania biznesowe nie wymagają żadnego filtrowania itp.) I już korzystam z bazy danych (dla inne dane relacyjne). Jednym z takich przypadków była aplikacja, która miała zapytania użytkownika - model relacyjny miał garść tabel do przechowywania takich rzeczy, jak warunki, warunki zagnieżdżone (OR / AND itd ...), opcje sortowania itp ... To było dość skomplikowane, a więc kiedy musieliśmy dodać nową funkcję, która wymagała zmiany w bazie danych. Zastąpiłem całą rzecz pojedynczą tabelą zapytań z serializowanym obiektem blob reprezentującym wszystkie pozostałe opcje.

Innym przypadkiem był system przetwarzający różne „zadania”. Było kilka różnych rodzajów zadań i każde zadanie miało inne parametry, bez żadnych wymagań biznesowych, aby móc wyszukiwać / filtrować zadania na podstawie tych parametrów. Przechowywanie tego jako relacyjnej bazy danych wymagałoby co najmniej 1 nowej tabeli dla każdego typu zadania, co utrudnia dodawanie nowych typów zadań. Zamiast tego parametry są przechowywane jako obiekt typu blob w bazie danych - każdy typ zadania jest odpowiedzialny za serializację i usuwanie serializacji swoich własnych parametrów.

Niezbyt często można natknąć się na takie scenariusze, jednak co jakiś czas pojawia się sytuacja taka jak powyższa, w której serializowanie danych obiektów blob oszczędza wysiłku, sprawia, że ​​aplikacja jest łatwiejsza w utrzymaniu i nie ma prawdziwych wad.

Justin
źródło
6

Justin Cave ma rację, że może to prowadzić do nadmiarowych danych, ale tak naprawdę zależy to od sposobu zaprojektowania bazy danych.

Podejście do serializowania całego obiektu w kroplę nie jest tak oburzające, jak większość ludzi tutaj uważa. W rzeczywistości w przypadku niektórych aplikacji może to być najlepszy projekt, jaki możesz zrobić, jak wyjaśniłem tutaj: /programming//a/12644223/1121352 .

Rzeczywiście, serializacja obiektu prowadzi do co najmniej dwóch korzyści:

1- Ograniczanie niedopasowania impedancji : niektóre typy Java są po prostu niedostępne w SQL, szczególnie jeśli używasz wielu klas i typów niestandardowych, dlatego konwersja obiektów Java na SQL może być ogromnym problemem, a nawet prowadzić do niejasności.

2- Większa elastyczność schematu . Rzeczywiście, schematy relacyjne są naprawdę świetne dla danych o tej samej strukturze, ale jeśli niektóre obiekty w obrębie jednej klasy mogą mieć różne właściwości w zależności od warunków w czasie wykonywania, schematy relacyjne mogą znacznie utrudnić przepływ pracy.

Tak więc z pewnością są zalety tego podejścia (przynajmniej tych dwóch, ale na pewno innych, których nie cytowałem), ale oczywiście ogromny koszt do zapłacenia polega na tym, że tracisz prawie wszystkie korzyści ze schematów relacyjnych.

Można jednak uzyskać to, co najlepsze z obu światów, jeśli dokładnie projektuje się bazę danych: nadal można ustawić schemat relacyjny (tj. Unikalne kolumny kluczy), używając atrybutów unikalnych dla każdego obiektu, a następnie przechowywać obiekt w obiekcie blob . W ten sposób nadal możesz zapewnić szybkie pobieranie obiektu, korzystając z unikalnego identyfikatora zdefiniowanego przez atrybuty obiektu, zmniejszając również nadmiarowość, jednocześnie eliminując niedopasowanie impedancji i zachowując pełną elastyczność obiektów Java.

Na marginesie, niektórzy twórcy DB podejmują kilka prób łączenia modeli relacyjnych i obiektowych, takich jak typ danych JSON w PostSQL i PostgreSQL, aby można było bezpośrednio przetwarzać JSON jak dowolną kolumnę relacyjną, a także SQL3 i OQL (Object Query Language), aby dodać (ograniczoną) obsługę obiektów do SQL.

Ostatecznie wszystko to jest kwestią projektu i kompromisu między modelem relacyjnym a modelem obiektowym.

/ EDYCJA po przeczytaniu komentarzy: oczywiście, jeśli dane muszą być możliwe do przeszukiwania („zapytania”), NIE należy przechowywać danych jako obiektu blob. Ale jeśli niektóre części danych nie mają być przeszukiwalne , ale raczej pewnego rodzaju metadane, wówczas przechowywanie tej części danych jako obiektu wewnątrz obiektu blob może być dobrym rozwiązaniem, szczególnie jeśli te metadane mają elastyczną strukturę i może zmieniać się z obiektu na obiekt.

gaboryczny
źródło
5

Podajmy praktyczny przykład tego, kiedy robiłem to w przeszłości.

Mamy bazę danych, która zawiera wszystkie dane dla aplikacji wielu użytkowników; baza danych ma również tabelę użytkowników z ich prawami dostępu. Wszystkie te dane są znormalizowane zgodnie z oczekiwaniami.

Następnie mamy prośbę, aby aplikacja pamiętała, jakie okna użytkownik otworzył i co robił, aby mógł przywrócić stan, gdy użytkownik rozpocznie pracę następnego dnia rano.

  • Po pierwsze, jeśli to czasami zawiedzie, czy nie jest to impertynenckie

    • Jeśli na przykład ktoś po raz pierwszy użyje nowej wersji aplikacji, zapomni o otwartych oknach, więc co…
  • Dlatego w przypadku zmiany obiektów dochodzi do 100% powrotu, więc nie możemy odczytać bloku.

  • Mamy już scentralizowaną bazę danych z kontrolą dostępu, tworzeniem kopii zapasowych itp.
  • Koszt przechowywania danych w plikach jest wysoki, ponieważ pliki będą musiały zostać umieszczone na jakimś serwerze plików, do którego mają dostęp wszystkie komputery użytkowników, lub trzeba będzie napisać API, aby odczytać te pliki.

Innym razem mieliśmy aplikację, która wykonała wiele długotrwałych obliczeń, a użytkownicy chcieli móc wznowić obliczenia od ostatniego momentu, w którym wiadomo, czy nastąpiła przerwa w dostawie prądu itp. Nie ma mowy, aby inna wersja można oczekiwać, że aplikacje ponownie uruchomią obliczenia, a ponieważ istnieje wiele obiektów wymagających zapisania, normalizacja danych byłaby droga.

Ponieważ baza danych już istnieje i jest używana dla dobrze zdefiniowanych znormalizowanych danych aplikacji i nie ma żadnego rzeczywistego powodu, aby nie używać jej do przechowywania blogów, wybraliśmy rozsądną i szybką opcję.

Ian Ringrose
źródło
4

Bardzo ważny czynnik: serializacja Javy (ta zrobiona, którą można włączyć przez implementację Serializable) jest sama w sobie bardzo złym formatem, więc nie powinieneś jej używać do trwałego przechowywania obiektów.

Wady serializacji Java to:

  • Dane nie są tak naprawdę czytelne z innych języków.
  • Utrzymanie kompatybilności do przodu szeregowanych obiektów nie jest bardzo łatwe, to znaczy: jeśli dodasz (lub usuniesz) pola do klasy, nie będzie tak łatwo odczytać obiekty utworzone przez wcześniejszą wersję klasy.
  • To nie jest tak szybkie (ale twój przebieg może się różnić)

Więc jeśli użyjesz innego formatu serializacji, otrzymasz ładny sklep z kluczowymi wartościami, jeśli użyjesz serializacji java, dostaniesz bałagan.

jb.
źródło
Fakty w odpowiedzi są po prostu fałszywe: 1) format jest objęty wyczerpującą specyfikacją; 2) dodawanie pól wcale nie stanowi problemu, format jest bardzo elastyczny; 3) prędkość zależy od rzeczywistych danych, ale jest porównywalna (czasem szybsza, czasem wolniejsza) z formatami takimi jak JSON lub XML. Zasadniczo cała odpowiedź jest błędna, z wyjątkiem jednego wiersza: „danych nie da się tak naprawdę odczytać z innych języków”.
fdreger
1
Poza 1)tym, że było źle, reszta odpowiedzi jest ważna w IMO. Jeśli chcesz mieć kontrolę nad deserialisaton - co jest potrzebne, gdy dodajesz / usuwasz pola (a zwłaszcza gdy masz pola końcowe), interfejsy wydają się nieporadne i musisz przesłonić więcej metod, które są potrzebne readObjecti readReplace(w przypadku pól końcowych).
jb.
Mylisz się, dodawanie i usuwanie pól nie wymaga pisania żadnych metod. Jeśli chodzi o końcowe pola - twoja pierwotna odpowiedź w ogóle nie wspomina o nich, a jeśli tak, to nie ma znaczenia (problem byłby wspólny dla wszystkich innych formatów). Wreszcie powiedzenie „Nie jest tak szybkie (ale przebieg może się różnić)” po prostu nic nie znaczy. Masz tylko jeden fakt: ten dotyczący innych języków. To bardzo słaba podstawa do nazywania czegoś „bałaganem”.
fdreger
1
Dodanie pól nie wymaga pisania żadnych metod, ale jeśli chcesz wpłynąć na sposób ich deserializacji, musisz określić to zachowanie. Spróbuję wykopać kilka odniesień do problemów z deserializacją ewoluującego schematu obiektowego.
jb.
3

To interesujący wątek z kilkoma przemyślanymi odpowiedziami. Nie znając wszystkich implikacji przechowywania i wyszukiwania zserializowanych obiektów, myślę, że warto udzielić odpowiedzi zespołowi DBA lub zespołowi programistów:

Kluczem do sukcesu jest spełnienie obecnych i przyszłych wymagań, a rozwiązanie powinno być tak proste, jak to możliwe, aby zminimalizować przyszłe wsparcie. Muszą być spełnione zarówno wymagania funkcjonalne, jak i wymagania niefunkcjonalne (np. Infrastruktura i baza danych). Pamiętaj o zasadzie 80/20. Zrozum znaczenie aplikacji dla firmy i jakie wysiłki rozwojowe są odpowiednie.

Nie rozłączaj się z miejscem, szybkością i pamięcią bazy danych, jeśli nie są to problemy.

Jeśli DBMS znajduje się na zatwierdzonej liście, możesz go użyć w rozwiązaniu, o ile koszty są odpowiednie. Nie ma problemu z użyciem relacyjnej bazy danych do przechowywania prostych obiektów blob, zwłaszcza jeśli upraszcza to wszystko.

Jeśli rozwiązaniem ma być prototyp lub wczesny etap / wersja, jeszcze większy nacisk należy położyć na utrzymanie prostoty. Zawsze możesz rozszerzyć schemat danych później, o ile go planujesz.

Pamiętaj, że relacyjne bazy danych nie wymuszają integralności ani spójności, chyba że schemat obejmuje samodzielny obszar biznesowy, a reguły biznesowe są surowe. (na przykład rozwiązanie pytania o obiekt szeregowy może rozważać repozytorium stylu słownikowego / ontologicznego w celu egzekwowania reguł).

Warto wziąć pod uwagę, że wszystkie relacyjne bazy danych nie używają czystych schematów relacyjnych baz danych (np. Gwiazdy, czasoprzestrzeń, nierelacyjne ..), również aplikacje mogą używać relacyjnych baz danych jako magazynów nierelacyjnych, jak w pytaniu. Wiele podstawowych biznesowych baz danych działa w ten sposób.

Dave
źródło