Il modo migliore (gratuito) per archiviare i dati? Che ne dite di aggiornamenti al file system?

StackOverflow https://stackoverflow.com/questions/142114

  •  02-07-2019
  •  | 
  •  

Domanda

Ho un'idea di come risolvere questo problema, ma volevo sapere se c'è qualcosa di più facile ed estendibile al mio problema.

Il programma su cui sto lavorando ha due forme base di dati: le immagini e le informazioni associate a quelle immagini. Le informazioni associate alle immagini sono state precedentemente archiviate in un database JET di estrema semplicità (quattro tabelle) che si sono rivelate lente e incomplete nei campi memorizzati. Stiamo passando a una nuova implementazione dell'archiviazione dei dati. Data la semplicità delle strutture dati coinvolte, pensavo che un database fosse eccessivo.

Ogni immagine avrà informazioni proprie (parametri di acquisizione), farà parte di un gruppo di immagini che sono correlate (prese nello stesso periodo di trenta minuti, diciamo), e quindi parte di un gruppo più grande (preso di la stessa persona). In questo momento, sto archiviando le persone in un dizionario con un identificativo univoco. Ogni persona ha quindi un Elenco dei diversi gruppi di immagini e ogni gruppo di immagini ha un Elenco di immagini. Tutte queste classi sono serializzabili e sto solo serializzando e deserializzando il dizionario. Roba abbastanza semplice. Le immagini sono memorizzate separatamente, in modo che il dizionario non diventi di dimensioni astronomiche.

Il problema è: cosa succede quando devo aggiungere nuovi campi di informazioni? Esiste un modo semplice per impostare queste strutture di dati in modo da tenere conto di potenziali revisioni future? In passato, il modo in cui avrei gestito questo in C era quello di creare una struttura serializzabile con molti byte vuoti (almeno una k) per la futura estensibilità, con uno dei byte nella struttura che indica la versione. Quindi, quando il programma legge la struttura, saprebbe quale deserializzazione utilizzare in base a un'enorme istruzione switch (e le versioni precedenti potrebbero leggere nuovi dati, poiché i dati estranei andrebbero semplicemente nei campi che vengono ignorati).

Esiste un tale schema in C #? Ad esempio, se ho una classe che è un gruppo di oggetti String e Int e quindi aggiungo un altro oggetto String alla struttura, come posso deserializzare un oggetto dal disco e quindi aggiungere la stringa ad esso? Devo rassegnarmi a disporre di più versioni delle classi di dati e di una factory che accetta un flusso di deserializzazione e gestisce la deserializzazione in base ad alcune informazioni sulla versione archiviate in una classe base? Oppure una classe come Dictionary è ideale per archiviare questo tipo di informazioni, poiché deserializzerà automaticamente tutti i campi sul disco e se ci sono nuovi campi aggiunti, posso semplicemente catturare le eccezioni e sostituire quelle stringhe e Ints vuote con quei valori?

Se seguo l'approccio del dizionario, c'è un aumento di velocità associato alla lettura / scrittura del file e ai tempi di recupero dei parametri? Immagino che se ci sono solo campi in una classe, il recupero dei campi è istantaneo, ma in un dizionario, c'è un piccolo overhead associato a quella classe.

Grazie!

È stato utile?

Soluzione

Al momento il mio cervello è impazzito, quindi non sono sicuro di poter consigliare a favore o contro un database, ma se stai cercando una serializzazione indipendente dalla versione, saresti uno sciocco a non almeno controllare Buffer di protocollo .

Ecco un breve elenco di implementazioni che conosco per C # /. NET:

Altri suggerimenti

Sqlite è ciò che desideri. È un database rapido, integrabile, a file singolo che ha collegamenti alla maggior parte delle lingue.

Per quanto riguarda l'estensibilità, è possibile memorizzare i modelli con attributi predefiniti e quindi disporre di una tabella separata per le estensioni degli attributi per future modifiche.

Un anno o due lungo la strada, se il codice è ancora in uso, sarai felice che 1) Altri sviluppatori non dovranno imparare una struttura di codice personalizzata per mantenere il codice, 2) Puoi esportare, visualizzare, modificare i dati con strumenti di database standard (esiste un driver ODBC per file sqlite e vari strumenti di query) e 3) sarete in grado di scalare fino a un database con minime modifiche al codice.

Solo un piccolo avvertimento, SQLLite, Protocol Buffers, mmap et al ... tutto molto buono ma dovresti prototipare e testare ogni implementazione e assicurarti che non colpirai gli stessi problemi perf o colli di bottiglia diversi.

La semplicità potrebbe essere solo l'upgrade a SQL (Express) (potresti rimanere sorpreso dal guadagno perfetto) e correggere tutto ciò che manca al design del database attuale. Quindi se perf è ancora un problema, inizia a studiare queste altre tecnologie.

Esiste uno schema di database, per il quale non ricordo il nome, che può gestire questo tipo di situazione. Fondamentalmente hai due tavoli. Una tabella memorizza il nome della variabile e l'altra memorizza il valore della variabile. Se si desidera raggruppare le variabili, aggiungere una terza tabella che avrà una relazione uno-a-molti con la tabella dei nomi delle variabili. Questa configurazione ha il vantaggio di consentire di continuare ad aggiungere variabili diverse senza dover continuare a modificare lo schema del database. Mi sono risparmiato parecchie volte quando ho a che fare con dipartimenti che cambiano idea frequentemente (come il marketing).

L'unico inconveniente è che la tabella dei valori variabili dovrà archiviare il valore effettivo come colonna stringa (in realtà varchar o nvarchar). Quindi devi affrontare la seccatura di riconvertire i valori nelle loro rappresentazioni native. Attualmente mantengo qualcosa del genere. La tabella delle variabili attualmente ha circa 800 milioni di righe. È ancora abbastanza veloce, poiché posso ancora recuperare alcune variazioni di valori in meno di un secondo.

Non sono un programmatore C # ma mi piace la chiamata mmap () e ho visto che c'è un progetto che fa una cosa del genere per C #.

Vedi Mmap

  

I file strutturati sono molto performanti se fatti su misura per un'applicazione specifica ma sono difficili da gestire e una risorsa di codice difficilmente riutilizzabile. Una soluzione migliore è un'implementazione simile alla memoria virtuale.

     
      
  • È possibile gestire fino a 4 gigabyte di informazioni.
  •   
  • Lo spazio può essere ottimizzato in base alle dimensioni dei dati reali.
  •   
  • Tutti i dati possono essere visualizzati come un singolo array e accessibili con operazioni di lettura / scrittura.
  •   
  • Non c'è bisogno di strutturare per memorizzare ma basta usare e archiviare.
  •   
  • Può essere memorizzato nella cache.   È altamente riutilizzabile.
  •   

Quindi vai con sqllite per i seguenti motivi:
1. Non è necessario leggere / scrivere l'intero database dal disco ogni volta
2. Molto più facile da aggiungere anche se all'inizio non lasci abbastanza segnaposto
3. Ricerca più semplice in base a tutto ciò che desideri
4. più facile modificare i dati in modi al di là dell'applicazione è stata progettata

Problemi con l'approccio del dizionario
1. A meno che non sia stato creato un dizionario intelligente, è necessario leggere / scrivere l'intero database ogni volta (a meno che non si progetta attentamente la struttura dei dati, sarà molto difficile mantenere la compatibilità con le versioni precedenti)
----- a) se non hai lasciato abbastanza segnaposti ciao ciao
2. Sembra che dovresti cercare in modo lineare tra tutte le foto per cercare uno degli attributi di acquisizione
3. Un'immagine può appartenere a più di un gruppo? Un'immagine può trovarsi sotto più di una persona? Due persone possono essere nello stesso gruppo? Con i dizionari queste cose possono diventare pelose ....

Con una tabella di database, se si ottiene un nuovo attributo, si può semplicemente dire Alter Table Picture Aggiungi Attribute DataType. Quindi, finché non imposti una regola in base alla quale l'attributo deve avere un valore, puoi comunque caricare e salvare versioni precedenti. Allo stesso tempo, le versioni più recenti possono utilizzare i nuovi attributi.

Inoltre non è necessario salvare l'immagine nel database. Potresti semplicemente memorizzare il percorso dell'immagine nel database. Quindi, quando l'app ha bisogno dell'immagine, basta caricarla da un file su disco. Ciò mantiene le dimensioni del database più piccole. Anche il tempo di ricerca aggiuntivo per ottenere il file del disco sarà molto probabilmente insignificante rispetto al tempo di caricamento dell'immagine.

Probabilmente il tuo tavolo dovrebbe essere
Immagine (PictureID, GroupID ?, Percorso file, Parametro acquisizione 1, Parametro acquisizione 2, ecc.)

Se vuoi maggiore flessibilità potresti creare una tabella CaptureParameter (PictureID, ParameterName, ParameterValue) ... Vorrei sconsigliare questo perché è molto meno efficiente di metterli in una tabella (per non parlare delle query per recuperare / cercare i parametri Capture sarebbe più complicato).

Person (PersonID, Any Person Attributes like Name / Etc.)
Gruppo (ID gruppo, Nome gruppo, ID persona?)
PersonGroup? (PersonID, GroupID)
PictureGroup? (GroupID, PictureID)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top