it-swarm.it

I file binari devono essere archiviati nel database?

Qual è il posto migliore per l'archiviazione di file binari correlati ai dati nel database? Dovresti:

  1. Archiviare nel database con un BLOB
  2. Archiviare sul filesystem con un collegamento nel database
  3. Archivia nel filesystem ma rinomina in un hash del contenuto e archivia l'hash nel database
  4. Qualcosa a cui non ho pensato

I vantaggi di (1) sono (tra gli altri) la preservazione dell'atomicità delle transazioni. Il costo è che potresti aumentare notevolmente i requisiti di archiviazione (e streaming/backup associati)

L'obiettivo di (3) è preservare l'atomicità in una certa misura - se riesci ad imporre che il filesystem in cui stai scrivendo non consente di modificare o eliminare i file e ha sempre l'hash corretto come nome file. L'idea sarebbe quella di scrivere il file nel filesystem prima di consentire l'inserimento/l'aggiornamento facendo riferimento all'hash - se questa transazione fallisce dopo la scrittura del filesystem ma prima del DML del database, va bene perché il filesystem 'finge' di essere il repository di tutti possibili file e hash - non importa se ci sono alcuni file che non vengono indicati (e potresti pulirli periodicamente se stai attento)

MODIFICARE:

Sembra che alcuni RDBMS lo coprano nei loro modi individuali - sarei interessato a sapere come lo fanno gli altri - e in particolare in una soluzione per postgres

  1. Archivia nel database con un BLOB

    Uno svantaggio è che rende i file del database abbastanza grandi e forse troppo grandi per il backup con la configurazione esistente. Un vantaggio è l'integrità e l'atomicità.

  2. Archivia sul filesystem con un collegamento nel database

    Mi sono imbattuto in tali disastri orribili nel farlo, e mi spaventa che la gente continui a suggerirlo. Alcuni dei disastri inclusi:

    • Un utente privilegiato che riorganizza i file e spesso interrompe i collegamenti tra i percorsi nel DB e dove sono ora (ma in qualche modo questo è diventato colpa mia).
    • Quando si sposta da un server a un altro, la proprietà di alcuni dei file viene persa come SID per l'account amministratore del vecchio computer (su cui era in esecuzione il vecchio sito Web) non faceva parte del dominio e quindi i file copiati avevano ACL che potevano non essere risolto presentando così agli utenti il ​​nome utente/password/prompt di accesso al dominio.
    • Alcuni dei percorsi hanno finito per essere più lunghi di 256 caratteri dal C:\ fino al .doc e non tutte le versioni di NT sono state in grado di gestire percorsi lunghi.
  3. Archivia nel filesystem ma rinomina in un hash del contenuto e archivia l'hash nel database

    L'ultimo posto in cui ho lavorato lo ha fatto sulla base della mia spiegazione degli scenari di cui sopra. Pensavano che fosse un compromesso tra l'incapacità dell'organizzazione di acquisire esperienza con database di grandi dimensioni (qualcosa di più grande di circa 40 G era considerato "troppo grande"), l'incapacità aziendale di acquistare dischi rigidi di grandi dimensioni e l'impossibilità di acquistare un back più moderno soluzione e la necessità di allontanarsi dai rischi n. 1 e n. 3 che ho identificato sopra.

La mia opinione è che l'archiviazione nel DB come BLOB sia una soluzione migliore e più scalabile in uno scenario multi-server, in particolare con problemi di failover e disponibilità.

61
Tangurena

Numero 1 per la completa integrità dei dati. Usa le altre opzioni se non ti interessa la qualità dei dati. È così semplice.

La maggior parte dei RDBMS ha comunque ottimizzazioni per l'archiviazione dei BLOB (ad es. Filestream di SQL Server)

29
gbn

Se stai cercando Oracle, dai un'occhiata a dbfs e Secure Files.

Secure Files dice tutto, mantieni TUTTI i tuoi dati al sicuro nel database. È organizzato in pallonetti. Secure Files è una versione modernizzata dei lob, che dovrebbe essere attivata.

dbfs è un filesystem nel database. Puoi montarlo in modo simile a un file system di rete, su un host Linux. È davvero potente. Vedi blog Ha anche molte opzioni per sintonizzarti sulle tue esigenze specifiche. Essendo un dba, dato un filesystem (basato sul database, montato su Linux), ho creato un database Oracle su di esso senza problemi. (un database, memorizzato in un ... database). Non che questo sarebbe molto utile, ma mostra il potere.

Ulteriori vantaggi sono: disponibilità, backup, ripristino, tutti letti coerenti con gli altri dati relazionali.

A volte viene data la dimensione come motivo per non archiviare documenti nel database. Probabilmente è necessario eseguire il backup dei dati in qualsiasi modo, quindi non è un buon motivo per non archiviarli nel database. Soprattutto in una situazione in cui i vecchi documenti devono essere considerati di sola lettura, è facile creare solo grandi parti del database in sola lettura. In tal caso, quelle parti del database non hanno più bisogno di un backup frequente.

Un riferimento in una tabella a qualcosa al di fuori del database non è sicuro. Può essere manipolato, è difficile da controllare e può facilmente perdersi. Che ne dici di transazioni? Il database offre soluzioni per tutti questi problemi. Con Oracle DBFS puoi consegnare i tuoi documenti ad applicazioni non di database e non saprebbero nemmeno che stanno frugando in un database.

Un'ultima, grande sorpresa, le prestazioni di un filesystem dbfs sono spesso migliori di un normale filesystem. Ciò è particolarmente vero se i file sono più grandi di pochi blocchi.

22
ik_zelf

Penso che la risposta giusta qui dipenda molto dalla tua domanda e da quanto siano importanti quei documenti.

Per un sistema di gestione dei documenti, o un sistema in cui la recuperabilità dei documenti archiviati è fondamentale (quindi la maggior parte delle cose finanziarie, relative a risorse umane o CRM), l'archiviazione di documenti in linea o l'utilizzo della tecnologia dei documenti proprietaria del fornitore DB preferito sembra la cosa giusta da fare.

Tuttavia, ci sono molte applicazioni in cui ritengo che la decisione opposta sia appropriata.

I sistemi di helpdesk e quelli di tipo wiki sono quelli in cui penso abbia molto senso conservare i dati out del database. Credo che alcuni, come Jira, forniscano effettivamente un'opzione per scegliere se archiviare i documenti in linea o meno.

Per un'azienda di medie dimensioni, l'archiviazione di documenti per un sistema di ticketing in linea può significare la differenza tra un backup compresso misurato in megabyte e uno misurato in gigabyte.

Personalmente preferirei riportare online un sistema di biglietteria in pochi minuti e lottare con i documenti (generalmente meno importanti) per alcune ore, piuttosto che aumentare il mio "si è rotto e il CTO mi sta respirando al collo" RTO dovendo ripristinare e riprodurre i registri da un backup molto più ampio.

Vi sono altri vantaggi nel mantenere separati i documenti.

  • È possibile eseguire facilmente processi separati che catalogano i metadati dei documenti, eseguono la scansione dei virus, eseguono l'indicizzazione delle parole chiave, ecc.
  • È possibile usufruire di strumenti per assistere con backup o ripristino (rsync, snapshot di archiviazione, ecc.) Che si prestano molto meglio ai file rispetto ai database
  • Puoi effettivamente utilizzare uno spazio di archiviazione che supporta la compressione o la deduplicazione (le cose che i tuoi SAN hanno fatto il trabocchetto per anni, alias la rovina degli amministratori di database in tutto il mondo)
  • Per un'installazione su più siti, è possibile integrare un database centralizzato con un file system distribuito

Penso che una combinazione ibrida di n. 2 e n. 3 potrebbe essere intelligente. Conserva i nomi dei file originali, ma calcola e archivia un hash/checksum del documento, in modo da avere un punto di riferimento che aiuti il ​​recupero nel caso in cui qualcuno sposti o rinomini il file.

Memorizzare i file con i loro nomi di file originali significa che le applicazioni possono letteralmente strapparli direttamente da un file system e inviarli via cavo, o in un mondo client spesso, magari anche indirizzare l'utente direttamente al file server.

15
Nathan Jolly

Non farlo.

Non c'è davvero un vantaggio nell'avere i file archiviati nel database.

Non ti sembra già strano e strano quando pensi a te stesso:

Devo archiviare i file in un database o in un filesystem ?

Ancora meglio, dillo ad alta voce.

Dai fatti:

Utilizzando il database

" [~ # ~] pros [~ # ~] " ... ma non del tutto :

  • "Atomicità" che è corretta ma è un'arma a doppio taglio. Perché trascina i contro insieme ad esso.
  • Integrità. Come sopra.

Non voglio davvero essere di parte ma non credo che ci sia altro da aggiungere. I professionisti non sono poi così fantastici se ci pensate.

Se ho dimenticato qualcosa di seguito, nel frattempo continua a leggere qui sotto.

CONS:

  • Strumento errato per il lavoro
  • Più difficile da mantenere
  • Lento
  • Dimentica la memorizzazione di centinaia di MB/gigabyte di dati PER utente .
  • Il backup di siti in rapida crescita sarà un incubo.
  • Anche il ripristino/spostamento farà schifo.

Utilizzando il filesystem

PROFESSIONISTI:

  • Molto più facile da mantenere
  • Veloce
  • I backup del database non hanno nulla a che fare con questo
  • Probabilmente più portabilità *

[~ ~ #] contro [~ ~] # :

  • Nessuna*

* Stampa fine

In questo momento ti stai chiedendo, tieni duro significa che non ci sono svantaggi ?! Come mai?

Il più grande errore qui è che le persone stanno cercando di avvitare una vite con un martello.

Il motivo principale e vorrei spingermi fino a dire solo il motivo per cui questo viene chiesto è a causa di collegamenti ai file .

Questo è un problema che il database non è destinato a risolvere. Sembra anche sciocco se ci pensi.

"Il database risolverà i miei problemi di collegamento dei file."

Quando in realtà, logicamente l'applicazione dovrebbe effettivamente essere responsabile della gestione dei collegamenti .

Una soluzione:

  1. Fai in modo che l'applicazione gestisca le richieste URL con percorsi personalizzati.
  2. Salva questo percorso nel tuo database.
  3. Internamente ogni volta che questo percorso viene chiamato mappalo sul file desiderato.
  4. Se mai spostate i vostri file altrove, cambiate semplicemente il valore del nome file della rotta e quella rotta servirà sempre lo stesso file, indipendentemente da dove è memorizzata o referenziata sul web.

Ciò eliminerebbe anche i percorsi nativi, renderebbe l'applicazione più portatile, gestibile e consentire di passare a qualsiasi tipo di filesystem senza interrompere nulla.

Per quanto riguarda come implementarlo va oltre lo scopo di questa risposta, ma puoi dare un'occhiata ad un esempio generale nel linguaggio web (PHP) più ampiamente usato:

https://github.com/symfony/Routing

https://github.com/kriswallsmith/assetic

Entrambi insieme sono davvero potenti.

14
Tek

Voglio aggiungere la mia esperienza qui per quanto riguarda i compromessi. In PostgreSQL, almeno, gli impatti sulle prestazioni sono piuttosto minimi in termini di server db. I BLOB di grandi dimensioni vengono archiviati in file separati, non nelle tabelle heap principali, in modo da spostarli al di fuori delle operazioni che possono contare un numero elevato di record. Altri dbs possono fare qualcosa di simile.

Il vantaggio principale è la capacità di conservare tutti i dati correlati in un unico posto per scopi di atomicità e backup. Ciò riduce notevolmente la possibilità che qualcosa vada storto.

Il principale svantaggio non è quello che ho visto sopra, e questo è l'utilizzo della memoria sul front-end. Non so esattamente come ogni db gestisce questo, quindi questo può dipendere dall'implementazione, ma per PostgreSQL, i dati arrivano come escape ASCII (possibilmente esadecimale, possibilmente con escape incorporati). poi deve essere riconvertito in binario nel front-end. Molti framework che ho visto per fare ciò implicano il passaggio del valore (non come riferimento) e quindi la costruzione di una nuova stringa binaria basata su di esso. Ho calcolato che usando Perl per fare questo finito per usare molte volte la memoria del binario originale per realizzare.

Verdetto: se ai file si accede solo occasionalmente, lo memorizzerei nel database. Se si accede frequentemente e ripetutamente, almeno con PostgreSQL, penso che i costi siano superiori ai benefici.

9
Chris Travers

Non archiviare i file in un database.

Tutti, senza eccezioni, che possono eseguire qualsiasi RDBMS sul mercato dispongono già di un database specifico per l'archiviazione dei file e lo stesso RDBMS lo sta utilizzando! Quel database è il filesystem . Ora parliamo di alcuni dei potenziali svantaggi dell'archiviazione dei file nel database, nonché di alcuni fattori attenuanti specifici per l'archiviazione dei file nel database.

  • No filehandes ai file nel database. Cosa significa?

    • Programmatore: non puoi NON PUOI cercare (fseek), non è possibile gestire la risorsa con accesso asincrono (asyncio o epoll), non esiste sendfile (salvando la copia dallo spazio del kernel).

    • Applicazione pratica: vuoi inviare un video o un'immagine a un client su HTTP2/3? Se è nel database, dovrai prima interrogarlo. Per qualsiasi query restituisca quel file, dovrai attendere che la query intera si concluda prima che quel file possa passare al passaggio successivo. In un'installazione di produzione con un rdbms su un server diverso rispetto al server Web, prima dovrai trasferire il file interamente dal rdbms al server web piuttosto che trasmetterlo in streaming. Tuttavia, se il livello di trasporto forniva l'astrazione del file system (che supporta anche NFS), è possibile cercare a metà del file e iniziare immediatamente a trasmetterlo nuovamente al client senza eseguire il buffering del file più del necessario. Questo viene fatto abitualmente dal server web nginx , Apache , PureFTP e ProFTP.

  • Doppia copia su RDBMS. Per il fatto stesso che si trova nel database, probabilmente lo scriverai due volte. Una volta in un registro write-ahead (WAL), quindi di nuovo nel tablespace.

  • Nessun aggiornamento, mai MVCC significa che nulla viene aggiornato, solo copiato di nuovo con modifiche , quindi la riga precedente viene contrassegnata come scaduta (eliminata). Qualsiasi aggiornamento del file richiederà la scrittura dell'intera riga , non solo del file nell'intera riga. Anche i filesystem possono fornire questo, con journaling dei dati, ma raramente ne hai bisogno.

  • Lettura e trasferimento dei file per rallentare la query Se il file stesso è archiviato in una riga di cui è necessario eseguire una query, l'intera riga dovrà attendi che il file venga trasferito o dovrai inviare due query separate.

  • Uso della memoria sul client DB. Il client DB (libpq, jdbc, odbc, freetds, ecc.) O simili probabilmente eseguirà il buffer della query in memoria. Quando quel buffer in memoria è esaurito, può avviare un buffer del disco o, peggio ancora, può ricadere nel kernel per essere impaginato sul disco.

  • Query-throttling molti database offrono la possibilità di uccidere e raccogliere query quando impiegano troppo tempo o risorse. Tieni presente che i trasferimenti di file non verranno dettagliati in nessuna implementazione. Quella query è stata uccisa dopo 3 secondi? O ha impiegato 1 secondo e il backend ha impiegato 2 secondi per trasferire un file? Non solo "dettagliati", come hai intenzione di dichiarare in modo efficace quanto tempo dovrebbe impiegare una query quando il 99,9% delle query restituisce 1 KB e l'altra restituisce 1 GB?

  • Nessuna copia su scrittura o deduplicazione XFS e BTRFS supportano la copia su scrittura e la deduplicazione in modo trasparente. Ciò significa che avere la stessa immagine ovunque o averne bisogno di una seconda copia può essere in modo trasparente gestito dal filesystem. Tuttavia, se il file non è autonomo e si trova su una riga o in un archivio, è probabile che il file system non sia in grado di deduplicarlo.

  • Integrità molte persone parlano di integrità. Cosa pensi sia meglio nel rilevare la corruzione del file system, un'applicazione che utilizza il file system o le utilità principali del file system? Archivia un file in una riga, o fuori linea e qualsiasi corruzione del file system verrà oscurata dal database. xfs_repair è dannatamente bravo a recuperare in caso di corruzione del file system o del disco rigido e, in caso di errore, sarà ancora più semplice eseguire analisi forensi dei dati.

  • Migrazione del cloud se mai vuoi archiviare i file su un SAN o il cloud avrai ancora di più difficoltà perché ora che la migrazione della memoria è una migrazione del database. Se i tuoi file sono ad esempio memorizzati nel file system, puoi spostarli abbastanza facilmente su S3 (e con qualcosa come s3fs può essere trasparente).

Eccezioni

La memorizzazione di file nel database ha alcuni casi d'uso validi,

  • Quando è necessario modificare il file in modo transitorio. Ciò significa che è letteralmente parte della transazione modificare il file. Oppure bisogno la possibilità di ripristinare le modifiche sul file se la transazione non riesce per problemi di integrità dei dati nelle relazioni (tabelle).
  • Quando hai bisogno di per assicurarti che il file system sia aggiornato con precisione con i dati e che non puoi permetterti alcun rischio nel mantenerli sincronizzati.
  • Quando il database può effettivamente analizzare il file e puoi interrogarlo. In PostgreSQL, ad esempio, le topologie possono essere query con PostGIS. A questo punto, sebbene sia un file, contiene anche dati per la query e non un dump della memoria.

Fattori attenuanti

  • Alcuni database hanno la nozione di "risorsa gestita esternamente" in cui il database gestisce il file privatamente sul disco come

  • Alcuni database archiviano oggetti binari di grandi dimensioni fuori linea o possono, come Oracle SecureFile. Ciò consente di aggiornare la riga, senza riscrivere il file.

  • Alcuni database come Oracle eseguono il proprio MVC senza un registro WAL e non devono raddoppiare la scrittura del file.

  • Alcuni database, come SQL Server e Oracle, offrono la possibilità di "eseguire lo streaming" dei dati dal file senza che sia necessario gestirlo. Questo può o non può essere eseguito su una connessione diversa rispetto alla query dei database. Ma la chiave qui è che mentre tu can esegui lo streaming del file (in teoria), non riesco a trovare alcuna prova di alcun prodotto non realizzato dal provider che utilizza quella funzione. Ad esempio, dov'è il bridge NGINX/Apache per permetterti di farlo?

  • Oracle fornisce la deduplicazione, la compressione e la crittografia opzionali tramite l'archiviazione LOB interna (come SecureFile).

Conclusione

Lo scenario peggiore quando si inserisce un file nel database è molto male per prestazioni e compatibilità con gli strumenti. Dipende sempre eccezionalmente dall'implementazione. Il database non è in alcun modo migliore di essere un file system rispetto al file system. In ogni modo, è un compromesso e anche quando si ottengono potenti funzioni di mitigazione (come nel caso di SecureFile), gli strumenti sono così scadenti che non è in realtà molto più di un punto di marketing a meno che l'intero stack non sia creato dal provider RDBMS.

Mantieni la semplicità e la regola generale è mantenere i file fuori dal DB .

Soluzione

Come dovresti archiviare i file o astrarre un filesystem in modo tale da funzionare efficacemente per più tenant e utenti? Sono parziale all'hash del contenuto del file. Questo è abbastanza comune in questi giorni e funziona bene.

9
Evan Carroll

In passato, Microsoft ha aumentato la capacità di archiviare immagini (e tipi di dati BLOB simili) nel database. Era una nuova fantastica funzionalità di SQL Server 2000 (sono abbastanza sicuro che fosse 2000, non 7.0) e molte persone sono saltate sul carro.

La memorizzazione di BLOBS nel database presenta vantaggi e svantaggi:

Da un lato, tutti i tuoi dati e le relative immagini o documenti possono essere archiviati e accessibili in un unico posto. L'utente dell'applicazione non richiede autorizzazioni di rete speciali, poiché è SQL che fornisce le immagini/i file/i documenti.

D'altra parte, il tuo database può crescere abbastanza grande, a seconda delle dimensioni e del numero di BLOBS che stai memorizzando. Ciò influisce su backup, requisiti di archiviazione, operazioni di ripristino sensibili al tempo, ecc.

SQL Server 2008 ha introdotto lo streaming di file. Il database contiene puntatori ai file, i file risiedono sul server non nel database, ma quando si esegue il backup del database, viene eseguito anche il backup dei file.

I tuoi backup possono diventare piuttosto grandi, ma non finisci con file/documenti/BLOB/immagini orfani.

La mia preferenza personale è stata quella di lasciare che il database memorizzasse i puntatori/i percorsi di rete e che un file server gestisse i file. I file server sono comunque ottimizzati per tali attività.

7
datagod

Il mio voto non sarebbe per nessuno dei due. Archivia i dati in un sistema come Amazon S3 o la CDN di Microsft e archivia tale URL nel database.

In questo modo si ottiene l'affidabilità di avere i dati sempre accessibili senza avere database di dimensioni mostruose da gestire.

6
paullb

Anche se dipende in parte dall'applicazione/ambiente (persone incluse), preferirei il BLOB.

Mantenere tutto nel database significa che la replica funziona per i dati dei file. Avresti bisogno di un meccanismo separato per sincronizzare FS.

In alcune applicazioni, il filesystem non dovrebbe essere modificato comunque. Ad esempio, su un sito Web di produzione, eviterei di utilizzare il filesystem per dati non disponibili (il sito vive in un SCM, i dati in un database).

Supponendo di avere più utenti/applicazioni con autorizzazioni separate, qualsiasi archivio di file system offre l'opportunità di differenze nel DB e FS diritti di accesso.

La raffinatezza che prenderei in considerazione per l'archiviazione BLOB è di frammentare i dati se ha senso; se hai bisogno solo di 512 byte da un BLOB da 20 Mb, questo accesso settoriale è un vero vantaggio, specialmente se hai a che fare con client remoti (e, di nuovo, un aggiornamento parziale crea molto meno traffico di replica).

6
Phil Lello

Per Postgres:

In realtà è direttamente diretto. Esiste un tipo BYTEA che può essere utilizzato per la memorizzazione di stringhe binarie. Per impostazione predefinita, non esistono utility integrate come quelle menzionate per MS o Oracle. Quindi archiviare molti file di grandi dimensioni e recuperarli può diventare noioso. Devi anche fare la conversione dei file all'interno dell'applicazione (come con un ByteStream o simile, non hai idea di come funzioni con le specifiche soluzioni di database file MS/Oracle <->). Esiste anche un tipo lo , che aiuta nel lavoro di gestione dei BLOB poiché alcuni gestori interni di questi tipi potrebbero non tenere traccia dei riferimenti.

3
DrColossos