Il professore ci ha detto di archiviare oggetti Java serializzati come BLOB anziché definire tabelle relazionali


21

Invece di definire effettivamente una tabella con gli attributi corretti, il mio professore ci ha detto che potevamo mappare gli oggetti su ID come questo:

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

Posso vedere così tanti problemi con questo; ridondanza dei dati, dover tenere traccia degli ID separatamente, dover inserire l'intera tabella in memoria per cercare qualcosa e ** se voglio cambiare il mio modello nel codice Java non sarò più in grado di deserializzare il BLOB archiviato nel database in quel modello.

O sono sempre bloccato con quel modello o devo fare qualche altra cosa davvero brutta per cambiare il mio modello. ** Tutto questo mi sembra una cattiva forma. Sono giustificato in disaccordo con il mio professore? C'è qualche vantaggio nel fare questo a cui non ho pensato? Se ho ragione, dovrei dire qualcosa al mio professore al riguardo? Stava predicando questo a tutta la mia classe e ha persino detto che ha costruito progetti in quel modo. Un secondo parere sarebbe fantastico.

Il corso si chiama Software Design .

Il mio professore non ha detto che questo era il modo migliore, ma ha detto che era un'alternativa legittima alla definizione di tabelle relazionali.

Il modello non è dinamico in alcun modo.


I commenti non sono per una discussione estesa; questa conversazione è stata spostata in chat .
Paul White dice GoFundMonica

Risposte:


34
  1. Non è, di per sé, una cosa negativa - affatto. Discutere di "che è meglio" senza un contesto adeguato (= requisiti esatti) è un esercizio di futilità.

  2. La parte in grassetto è sbagliata. È possibile estendere facilmente oggetti già serializzati per aggiungere nuovi campi e ottenere la piena compatibilità binaria con gli oggetti più vecchi. Puoi anche semplicemente creare nuove classi invece di cambiare quelle originali.

La discussione con il professore dovrebbe concentrarsi sui pro e contro del "negozio relazionale" rispetto al "negozio di valori-chiave" in diversi scenari, non sull'astratta "scommessa". Oppure potresti anche discutere se il Natale è superiore al Ringraziamento.

- una modifica, dopo aver letto altre risposte.

Una delle altre risposte arriva al punto di affermare che "è difficile immaginare un caso in cui i professionisti superino i contro".

Poiché l'intera discussione deve riguardare problemi concreti (altrimenti non possiamo nemmeno definire "migliore" e "peggiore"), lasciatemi fare un esempio concreto. È completamente inventato, ma ho cercato di dare più dettagli possibili.

Immagina di avere un sito di giochi online, con un database che memorizza le statistiche dei giocatori in diversi giochi online (giocati nel browser, scritti in GWT e compilati in javascript). Alcuni dei giochi sono strategici, alcuni sono giochi d'azione, altri sono platform. Il database è relazionale e memorizza i giocatori e la storia delle giocate e il punteggio.

Un giorno ottieni un requisito aggiuntivo: lascia che i giocatori salvino lo stato del gioco sul cloud, durante il gioco, in modo che possano riavviare il gioco in un secondo momento, nello stesso punto. Inutile dire che l'unica ragione per memorizzare questo stato temporaneo è tornare al gioco, lo stato stesso non sarà mai introspetto.

Ora hai due scelte di base:

  • poiché i giochi sono scritti in Java, puoi prendere facilmente il modello, inviarlo al server, serializzarlo in una riga di codice e archiviarlo come un BLOB. Il tavolo si chiamerà "save_games" e avrà chiavi esterne per il giocatore e così via. Dal punto di vista del database un "salvataggio di gioco" è un blob opaco, indivisibile.

  • puoi creare un modello relazionale separato per ciascuno dei tuoi 100 giochi (saranno decine di tavoli per gioco). Solo per Pacman, ad esempio, dovrai disporre di un tavolo in cui sono memorizzate le posizioni di tutte le palline, bonus, posizioni e stato attuale dei fantasmi non sfruttati. Se qualcuno, un giorno, modifica il gioco, anche leggermente, dovrai aggiornare il modello relazionale. Inoltre, per ogni tipo di gioco, dovrai implementare una logica per scrivere il modello Java nel database e rileggerlo.

La risposta di Justin Cave dice che dovresti scegliere la seconda opzione. Penso che questo sarebbe un enorme errore.

Inoltre, ho la sensazione che la percezione di Justin Cave sia che ciò che ho presentato sopra sia un caso "marginale" o "raro". Credo che, a meno che non sia in grado di presentare una sorta di dati concreti (basato su un campionamento rappresentativo di tutti i progetti IT nel mondo, non solo, diciamo, applicazioni aziendali negli Stati Uniti), considererò tale opinione un classico caso di proiezione bias.

In realtà, il problema degli oggetti Java serializzati in un database relazionale è molto più profondo di quanto sembri. Tocca il nucleo stesso dell'1NF, ovvero qual è il dominio di un attributo? . Se sei davvero interessato all'argomento, c'è un ottimo articolo di CJ Date, nel suo Date on Database: Writings 2000-2006 .


I commenti non sono per una discussione estesa; questa conversazione è stata spostata in chat .
Paul White dice GoFundMonica

22

Le persone possono (e fanno) realizzare con successo progetti che fanno questo genere di cose? Sfortunatamente, sì, lo fanno ragionevolmente spesso.

è un buon approccio? No non lo è. Praticamente stai prendendo il tuo database relativamente costoso e trasformandolo in un file system relativamente lento. Se vuoi davvero costruire un sistema che salvi il suo stato serializzando e deserializzando oggetti, puoi anche usare un file system piuttosto che usare un database.

Se costruisci sistemi che archiviano dati serializzando oggetti nel database, non farai amicizia con il tuo DBA. Finirai per archiviare dati ridondanti. Finirai con dati terribilmente incoerenti - ogni volta che i dati condivisi vengono aggiornati, alcuni oggetti finiranno con i nuovi valori e alcuni oggetti finiranno con i vecchi valori. Renderai impossibile fare qualsiasi tipo di segnalazione sui dati: tutto ciò che chiunque vuole fare con i dati richiederà a qualcuno di scrivere codice aggiuntivo. Questo è un grosso, enorme problema nella maggior parte delle aziende perché vogliono fare cose come estrarre i dati da un sistema per caricarli in un altro sistema o avere un sistema di reporting in grado di fornire report da più applicazioni front-end. Inoltre, come fai notare, dovrai costantemente affrontare i problemi quando "

Ci sono vantaggi in questo approccio? Immagino che tu possa sostenere che è abbastanza semplice implementare la prima versione dell'app. E consente allo sviluppatore di ignorare completamente tutto ciò che riguarda l'interazione corretta con un database. Sono difficile immaginare molti casi in cui questi vantaggi superano i numerosi aspetti negativi dell'approccio.

Quanto a come dovresti occuparti di questo professore in particolare, questo è un problema separato (e probabilmente fuori dal campo di applicazione di questo forum). Se il tuo professore sta attivamente sviluppando progetti nel mondo reale, probabilmente non sarà terribilmente ricettivo a qualsiasi argomento di uno studente sul fatto che il suo approccio sia fondamentalmente sbagliato (anche se l'approccio è davvero fondamentalmente sbagliato). Potresti essere servito meglio facendo il tuo progetto come vuole il professore e imparando il modo corretto di salvare i dati da solo (o in un corso diverso).


2
Quello che hai detto, oltre ai miei due centesimi. La riusabilità riguarda la modularità e la condivisione. Il modello a oggetti si concentra sulla condivisione di oggetti e sul riutilizzo del codice. Il modello di database si concentra sulla condivisione e il riutilizzo dei dati. Nessuno dei due modelli è completamente idiota. Nessuno dei due modelli è la perfezione. Ed è molto, molto difficile conciliare i due.
Walter Mitty,

1
Sono d'accordo con questo, ma odio vedere un professore insegnare qualcosa e dire che è il modo migliore senza essere confrontato. Che dire di tutti gli altri poveri studenti nella classe che andrà nel mondo reale pensando che questa sia la strada giusta?
Kevin,

Sicuro. Questa formulazione equivale a oggetti che fingono di essere dati. E sono dati, ma non molto utili.
Walter Mitty,

Il vantaggio è quasi sempre cancellato non appena si desidera rilasciare v2 dell'app.
Andy,

10

Ci sono situazioni in cui questo tipo di design è sensato, senza che tu descriva quali sono i tuoi progetti e come viene utilizzato, è difficile dire se questo sia appropriato o meno.

Il tuo DBA potrebbe odiarti se archivi BLOB, ma in molte situazioni l'unica alternativa è trasformare le tabelle in valore-attributo-entità, che ottiene ancora più odio dai DBA. L'altra alternativa è quella di utilizzare un database non relazionale, di solito database basati su oggetti o basati su dizionario o un database orientato ai documenti, che alcuni DBA, in particolare quelli che conoscono solo relazionali, odierebbero con ancora più passione. Il database non relazionale ha i suoi problemi da affrontare, tuttavia, può certamente essere il caso che l'utilizzo del database degli oggetti per archiviare gli oggetti possa esporre altri problemi che si sarebbero potuti risolvere facilmente nei sistemi relazionali.

C'è qualche vantaggio nel fare questo a cui non ho pensato?

La memorizzazione di oggetti serializzati significa che è possibile archiviare dati schematici (si noti che, nonostante il nome, lo schema non di solito significa che in realtà non esiste affatto uno schema, ma piuttosto c'è solo uno schema implicito). Esistono molti domini problematici in cui non è possibile definire in anticipo lo schema in fase di sviluppo e in cui seguire il tradizionale design del database relazionale significherebbe che è necessario modificare lo schema del database ogni due settimane o che si finisce con una tabella che ha L'80% delle colonne non utilizzate l'80% delle volte, o centinaia di tabelle diverse per archiviare gli stessi dati, nessuno dei quali indica un buon design. La radice di questo problema è in genere dovuta al fatto che si sta forzando l'adattamento di un dominio problematico non relazionale in un database relazionale.

Naturalmente, ci sono molti progetti in cui le persone pensano di dover usare EAV, schemaless o negozio di BLOB che si traducono in inutilmente causare quello che sarebbe stato un dolore evitabile. Dovresti assolutamente discutere con il tuo professore qual è il suo ragionamento e fornire i tuoi argomenti; ascolta gli argomenti e sii pronto a finire per essere d'accordo con lui, oppure no, forse ha torto.


7

L'ho già fatto in precedenza - è una tecnica utile in alcuni scenari, tuttavia dipende dal formato di serializzazione utilizzato. Se lo faccio, mi assicuro di utilizzare un formato di serializzazione che mi consente di annullare la serializzazione delle versioni precedenti del mio modello (ad es. XML).

Normalmente lo userei in scenari in cui il formato dei dati si tradurrebbe in un modello relazionale complicato che non offre vantaggi (ad esempio quando i requisiti aziendali non richiedono alcun filtro, ecc ...) e sto già utilizzando un database (per altri dati relazionali). Uno di questi casi era un'applicazione che presentava query degli utenti: il modello relazionale aveva una manciata di tabelle per archiviare cose come condizioni, condizioni nidificate (OR / AND ecc ...), opzioni di ordinamento ecc ... Era piuttosto complicato e quindi quando dovevamo aggiungere una nuova funzionalità che richiedeva una modifica al database. Ho sostituito l'intera cosa con una singola tabella di query con un BLOB serializzato che rappresenta tutte le altre opzioni.

Un altro caso era un sistema che elaborava vari "lavori". Esistevano diversi tipi di lavori e ogni lavoro aveva parametri diversi, senza requisiti aziendali per poter cercare / filtrare i lavori in base a tali parametri. La memorizzazione di questo come database relazionale avrebbe richiesto almeno 1 nuova tabella per tipo di lavoro, rendendo difficile l'aggiunta di nuovi tipi di lavoro. Invece i parametri vengono archiviati come BLOB nel database: ogni tipo di lavoro è responsabile della serializzazione e della deserializzazione dei propri parametri.

Non molto spesso ti imbatterai in scenari come questo, tuttavia ogni tanto si verifica una situazione come quella sopra in cui la serializzazione dei dati BLOB ti fa risparmiare un sacco di sforzo, rende la tua applicazione più gestibile e non ha veri svantaggi.


6

Justin Cave ha ragione nel dire che ciò può portare a dati ridondanti, ma ciò dipende davvero da come si progetta il database.

L'approccio di serializzare un intero oggetto in un BLOB non è così scandaloso come la maggior parte delle persone qui pensa che lo sia. In effetti, per alcune applicazioni, questo può essere il miglior design che puoi fare, come ho spiegato qui: /programming//a/12644223/1121352 .

In effetti, la serializzazione di un oggetto comporta almeno due vantaggi:

1- Riduzione della mancata corrispondenza dell'impedenza : alcuni tipi Java non sono disponibili in SQL, in particolare se si utilizzano molte classi e tipi personalizzati, la conversione avanti e indietro da oggetti Java in SQL può essere una seccatura enorme e persino portare ad ambiguità.

2- Maggiore flessibilità nel tuo schema . In effetti, gli schemi relazionali sono davvero ottimi per i dati che condividono la stessa struttura, ma se alcuni dei tuoi oggetti all'interno di una singola classe possono avere proprietà diverse a seconda delle condizioni in fase di esecuzione, gli schemi relazionali possono ostacolare in modo significativo il flusso di lavoro.

Quindi, ci sono sicuramente vantaggi in questo approccio (almeno questi due, ma certamente altri che non ho citato), ma ovviamente l'enorme costo da pagare è che perdi quasi tutti i benefici degli schemi relazionali.

Tuttavia, è possibile ottenere il meglio da entrambi i mondi se si progetta attentamente il database: è comunque possibile impostare uno schema relazionale (ad esempio: colonne chiave univoche) utilizzando gli attributi univoci per ciascun oggetto, quindi archiviare l'oggetto nel BLOB . In questo modo, puoi comunque assicurarti il ​​rapido recupero del tuo oggetto dato un identificatore univoco che è definito dagli attributi del tuo oggetto, riducendo anche la ridondanza, mentre annulli la mancata corrispondenza dell'impedenza e mantieni la piena flessibilità degli oggetti Java.

Come nota a margine , ci sono alcuni tentativi da parte di alcuni produttori di DB di fondere insieme modelli relazionali e di oggetti, come il tipo di dati JSON in PostSQL e PostgreSQL in modo da poter elaborare direttamente JSON come qualsiasi colonna relazionale, e anche SQL3 e OQL (Object Query Language) per aggiungere il supporto (limitato) di oggetti in SQL.

Alla fine, questa è tutta una questione di design e di compromesso tra il modello relazionale e il modello a oggetti.

/ EDIT dopo aver letto i commenti: ovviamente, se i tuoi dati devono essere ricercabili ("interrogabili"), NON devi archiviarli come BLOB. Ma se alcune parti dei tuoi dati non sono pensate per essere ricercabili , ma piuttosto un qualche tipo di metadati, archiviare questa parte di dati come oggetto all'interno di un BLOB può essere una buona soluzione, specialmente se questi metadati hanno una struttura flessibile e può cambiare da oggetto a oggetto.


5

Facciamo un esempio pratico di quando l'ho fatto in passato.

Abbiamo un database che contiene tutti i dati per un'applicazione muli-user; il database ha anche una tabella di utenti con i loro diritti di accesso. Tutti questi dati sono normalizzati come previsto.

Quindi abbiamo una richiesta che l'applicazione ricordi quali finestre un utente aveva aperto e cosa stava facendo, in modo che potesse ripristinare lo stato quando l'utente inizia a lavorare la mattina successiva.

  • In primo luogo se questo a volte fallisce, non è impertinente

    • Ad esempio, se la prima volta che qualcuno usa una nuova versione dell'applicazione, dimentica le finestre che aveva aperto, quindi cosa ...
  • Pertanto, se gli oggetti cambiano, si verifica un fallback del 100% e pertanto non è possibile leggere il blocco.

  • Abbiamo già un database centralizzato con controllo degli accessi, backup, ecc.
  • Il costo per l'archiviazione dei dati nei file è elevato, poiché i file dovranno essere inseriti in una sorta di file server a cui hanno accesso tutti i computer degli utenti, oppure dovrà essere scritta un'API per leggere questi file.

Un'altra volta , avevamo un'applicazione che eseguiva molti calcoli a lungo termine e gli utenti desideravano poter riavviare i calcoli dall'ultimo punto noto in caso di interruzione di corrente, ecc. Non è possibile che una versione diversa di ci si poteva aspettare che le applicazioni riavviassero i calcoli e poiché c'erano molti oggetti che dovevano essere salvati, normalizzare i dati sarebbe stato costoso.

Dato che il database era già in atto e utilizzato per i dati dell'applicazione ben definiti e normalizzati, e non essendoci alcun motivo reale per non utilizzarlo per archiviare i blog, abbiamo scelto l'opzione ragionevole e rapida.


4

Un fattore molto importante: la serializzazione Java (quella abilitata dall'implementazione Serializable) è di per sé un formato pessimo, quindi non dovresti davvero usarla per l'archiviazione permanente degli oggetti.

Gli svantaggi della serializzazione java includono:

  • I dati non sono realmente leggibili da altre lingue.
  • Mantenere la compatibilità diretta degli oggetti serializzati non è molto semplice, vale a dire: se si aggiungono (o si rimuovono) campi alla classe non è così facile leggere gli oggetti creati dalla versione precedente della classe.
  • Non è così veloce (ma il tuo chilometraggio può variare)

Quindi, se si utilizza qualsiasi altro formato di serializzazione, si ottiene un buon archivio di valori-chiave, se si utilizza la serializzazione java si ottiene disordine.


I fatti nella risposta sono semplicemente falsi: 1) il formato è coperto da una specifica esaustiva; 2) l'aggiunta di campi non è affatto un problema, il formato è molto flessibile; 3) la velocità dipende dai dati effettivi, ma è paragonabile (a volte più veloce, a volte più lento) a formati come JSON o XML. Fondamentalmente, l'intera risposta è sbagliata, tranne una riga: "i dati non sono realmente leggibili da altre lingue".
fdreger,

1
A parte il fatto 1)che il resto della risposta era errato, l'IMO è valido. Se vuoi avere il controllo sulla deserializzazione - che è necessario quando aggiungi / elimini campi (e specialmente quando hai campi finali) le interfacce sembrano goffe e devi scavalcare più metodi che è necessario readObjecte readReplace(per campi finali).
jb.

Ti sbagli, l'aggiunta e la rimozione di campi non richiede la scrittura di alcun metodo. Per quanto riguarda i campi finali: la risposta originale non li menziona affatto e, in caso affermativo, sarebbe irrilevante (il problema sarebbe comune per tutti gli altri formati). Infine, dire "Non è così veloce (ma il tuo chilometraggio può variare)" non significa semplicemente nulla. Hai solo un fatto giusto: quello sulle altre lingue. Questa è una base molto debole per chiamare qualcosa "un casino".
fdreger,

1
L'aggiunta di campi non richiede la scrittura di alcun metodo, ma se si desidera influenzare la modalità di deserializzazione, è necessario specificare tale comportamento. Proverò a trovare alcuni riferimenti a problemi con la deserializzazione dello schema di oggetti in evoluzione.
jb.

3

Questo è un thread interessante con alcune risposte ben ponderate. Non conoscendo tutte le implicazioni della memorizzazione e del recupero di oggetti serializzati, penso che sarebbe interessante fornire la risposta che potrei dare a un team DBA o team di sviluppo:

La chiave è soddisfare i requisiti attuali e futuri e mantenere la soluzione il più semplice possibile in modo da ridurre al minimo il lavoro di supporto futuro. Devono essere soddisfatti sia i requisiti funzionali sia i requisiti non funzionali (ad es. Infrastruttura e database). Ricorda la regola 80/20. Comprendi l'importanza dell'app per l'azienda e quali sforzi di sviluppo sono appropriati.

Non rimanere bloccato su spazio del database, velocità e memoria se non sono problemi.

Se un DBMS è nell'elenco approvato, è possibile utilizzarlo in una soluzione purché i costi siano appropriati. L'utilizzo di un database relazionale non consente di archiviare BLOB semplici, soprattutto se ciò semplifica le cose.

Se la soluzione deve essere un prototipo o una fase / versione iniziale, c'è ancora più stress da porre nel mantenere le cose semplici. È sempre possibile estendere lo schema dati in un secondo momento, purché lo si pianifichi.

Ricorda che i database relazionali non applicano integrità o coerenza a meno che lo schema non copra un'area di business autonoma e le regole aziendali siano rigorose. (ad esempio, la soluzione alla domanda con oggetto serializzato può prendere in considerazione un repository di stile dizionario / ontologia per applicare le regole).

Vale la pena considerare che tutti i database relazionali non usano schemi di database relazionali puri (ad esempio stelle, spaziali, non relazionali ...), anche le app possono utilizzare i database relazionali come archivi non relazionali, come nella domanda. Molti database di core business funzionano in questo modo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.