Devo memorizzare le immagini nel mio database o nel file system in questa applicazione? [duplicare]

10

Sto usando ASP.NET MVC 4 e SQL Server 2012. Non ho problemi ad andare a nessuna di queste soluzioni, ma voglio sapere quale si adatta meglio alla particolare applicazione che sto creando ora.

Sto facendo una specie di applicazione di sistema di libreria. Le uniche immagini che l'applicazione memorizzerà sono:

  • Immagini del profilo degli utenti (1 per utente)
  • Immagini del profilo delle biblioteche (1 per libreria)
  • Immagini degli autori di libri (1 per autore)
  • Immagini di copertina del libro (1 per libro)

Nessuna delle immagini memorizzate dovrà essere di alta qualità. Quindi ovviamente le immagini non sono una grande parte dell'applicazione e, considerando questo, sto attualmente memorizzando le immagini nel mio database. Anche se ho notato qualcosa che ritengo sia di grande aiuto.

Le immagini vengono recuperate utilizzando un Url.ActionLink che porta a un metodo di azione Controller che accetta (per esempio) un parametro bookId prima di raggiungere il database, recuperando l'immagine di quel libro e inviandola indietro. Quindi, se un utente dovesse cercare dei libri e alla fine otterrà un elenco di libri insieme alle loro immagini prima di lui, ci sarà una nuova chiamata al metodo di azione che recupera le immagini e una nuova query al database per ogni immagine elencata.

C'è un modo migliore di gestirlo? Dovrei riconsiderare il mantenimento delle mie immagini nel database o non è un grosso problema?

EDIT: non considererebbe questa domanda un duplicato perché appartiene a un tipo specifico di un'applicazione che gestisce pochissimi dati di immagine rispetto a qualsiasi tipo di un'applicazione (come nel < a href="https://softwareengineering.stackexchange.com/questions/105191/what-are-the-best-tips-for-storing-images-in-a-database"> domanda collegata ). Ovviamente, quando non sei sicuro di quanti dati di immagine stai memorizzando, è sempre meglio memorizzare le immagini sul file system. Questo non è un caso. La natura delle risposte qui rispetto alle risposte qui lo mostra.

    
posta Alternatex 29.10.2014 - 15:03
fonte

5 risposte

9

Perché non fare entrambe le cose? Il database è il supporto, l'ultimo negozio per l'immagine. La parte pubblica può essere una semplice lettura di db, ma è possibile estenderla facilmente in una cache del disco read-through e anche trarre vantaggio da numerosi trucchi infrastrutturali per migliorare al meglio le prestazioni.

Le vincite qui sono:

  • backup dei dati più semplice - i backup del database sono divertenti e facili, nessun file system che tocchi necessario
  • storia di sviluppo semplificata - non è necessario gestire un gruppo di file, basta che il team di sviluppo abbia una copia del database
  • più facile scrivere l'immagine - i file system sono un PITA, dalle autorizzazioni, ai cambiamenti di posizione dalla produzione di q > alla produzione, alla contesa alla mancanza di transazioni. Se le scritture stanno andando al db, risolvi il 90% di questi problemi.
  • i moderni database possono gestirli - presumendo che stiamo parlando di dimensioni di file di immagine abbastanza tipiche che misurano meno di pochi megabyte, i più moderni sistemi di database possono gestirli molto bene. Non è il problema dell'omicidio del database che alcuni vecchi articoli vorrebbero far credere.
risposta data 29.10.2014 - 15:25
fonte
5

Ci sono preoccupazioni valide su entrambi i lati del dibattito, quindi considera sempre i tuoi requisiti e i tuoi limiti. Quanti dati, quante immagini, quanto grande, quanto sicuro, il tempo di recupero?

Archiviazione BLOB in linea

Upside

  • Controllo della versione / coerenza transazionale. Questa è la differenza semantica chiave. Questo è gestito bene dal DB, quindi consente il recupero point-in-time. I file system non forniscono questo in modo da non avere la possibilità di eseguire il rollback. (Non mi riferisco al filesystem standalone, mi riferisco al problema del controllo transazionale dal tuo codice). Immagini e documenti possono essere corrotti dall'errore dell'utente, o fuori sincrono, diventando un problema di commit a 2 fasi. Alcuni sistemi risolvono questo problema aggiungendo un sistema di controllo di revisione esterno, ma richiede l'integrazione.
  • Semplifica l'implementazione
  • Tutti i dati delle app sono autonomi - Semplifica il backup e il ripristino o la migrazione del sistema fino a quando l'ingombro dei dati del blob non è ingombrante; basta fare un dump, eseguire il backup, esportare (qualunque sia il termine per il gusto del DB) e spostarlo nel nuovo database. Nessun file esterno da sincronizzare.
  • Il controllo della sicurezza / degli accessi è più pulito; accesso a un'immagine BLOB è intrinseco all'accesso alla riga di dati. Se un documento si trova all'esterno del DB e lasciamo che il server HTTP lo prelevi (al di fuori dell'app MVC), potrebbe essere migliore per la concorrenza e la scalabilità, ma fa più attenzione a garantire che l'Autorizzazione venga applicata ai file esterni poiché sono il DB dati. Ho verificato i progetti in cui file di grandi dimensioni sono stati archiviati fuori linea, sotto URL statici e multiplex e il mio primo scenario di test è quello di tentare l'accesso diretto all'URL statico senza autenticazione. Se si ospitano documenti protetti al di fuori del DB, non servirli in modo statico e assicurarsi che la politica di sicurezza copra il controllo di accesso delle immagini tra inquilini. L'autenticazione del server HTTP deve integrarsi con l'autenticazione generale del sistema. Questa è una grande preoccupazione nei database multi-tenant. Meno preoccupante in un singolo scopo, sistemi a singolo tenant, con autenticazione semplice.
  • Area di superficie del server di database ridotta - In molti sistemi, il DB è separato dal server delle app e nel mezzo c'è un firewall. Tutto può essere servito attraverso una singola porta DB (1433 / MSSQL) o (1521 / Oracle) come esempio. Con i file, se si sposta il DB su un livello separato, è necessario utilizzare NFS o NAS o replicare i file tra il server delle app se si esegue il ridimensionamento.

Downside

  • Tempi di backup - Per database veramente VERAMENTE di grandi dimensioni (non applicabili a te), il backup e il recupero diventano frustranti e iniziano a diventare problematici e costosi; mentre potresti avere un piccolo set di dati core altrimenti, potresti avere molti GB o TB di dati di immagine. Trattare tutto come un unico database coerente è buono dal punto di vista dell'integrità, ma è dannoso per il backup e il ripristino a meno che non si utilizzino i DBMS con backup e ripristino di livello enterprise (ad esempio Oracle RMAN e backup rolling, EMC BCV o Netapp Snapshots). A un cliente, il nostro DB è diventato così grande, abbiamo appena smesso di eseguire il backup e ci siamo impegnati in repliche geograficamente ridondanti. Un altro caso ben noto è stato Starbucks (i DBA hanno messo online la carta, è interessante leggere se ci sei dentro).
  • Tempo di recupero (noto anche come obiettivo del tempo di recupero o SLA di ripristino): spesso definito dal cliente. Come DBA devi tornare indietro se il cliente lo ha già dichiarato. Se l'aggiunta del 90% alle dimensioni del database per archiviare immagini non sicure influisce sul SLA di ripristino dei dati critici, allora non farlo.
  • Meno flessibilità. Non è semplice accedere ai documenti con le utilità del livello OS, i comandi della shell, ecc.

Personalmente, in questo contesto, penso che le scale siano impilate a favore dell'archiviazione DB in linea. Se il tuo DB non è grande, tieni tutto nel DB.

    
risposta data 30.10.2014 - 05:54
fonte
4

So if a user were to search for books and he ends up getting a list of books along with their images before him, there will be a new call to the action method that retrieves images and a new query to the database for each image listed.

Suggerirei che sia una buona cosa. Le immagini impiegano molto più tempo per trasferire del testo, quindi, anziché aspettare che entrambi caricino dal DB, puoi mostrare il testo e caricare le immagini separatamente.

Inoltre, se la tua applicazione dovesse avere successo, potresti voler eseguire la tua applicazione web su più server. A quel punto, ogni server avrà accesso al database, ma non al file system dell'altro server.

Tuttavia, dovresti considerare di isolare le immagini nella loro tabella immagine. Non memorizzare un'immagine nella stessa tabella del libro; è sufficiente memorizzare un ID immagine e utilizzarlo per recuperare l'immagine in un secondo momento. Questo è molto più efficiente, considerando il modo in cui i database gestiscono i dati sul disco. Questa affermazione è molto più importante se prevedi di cambiare l'immagine associata a un libro in qualsiasi punto.

Infine, la mia esperienza con queste cose è che ti colpiranno molto rapidamente in una situazione in cui desideri utilizzare una rete di Content Delivery per l'archiviazione di immagini (vedi AWS CloudFront o Azure CDN o CloudFlare), che è davvero il meglio di entrambi mondi: una memoria secondaria a cui è possibile accedere direttamente dall'URL, senza nemmeno preoccupare la tua app, e non tanto lavoro extra. Passare a un CDN è una modifica molto semplice se hai isolato le immagini nella loro tabella.

Oppure, ora puoi solo cercare una soluzione CDN e non preoccuparti mai più di nuovo.

    
risposta data 29.10.2014 - 15:25
fonte
3

Sconsiglio di memorizzare le immagini nel database.

Non è quello a cui è destinato il database - non sono dati relazionali che si riferiscono ad altri dati. Prende facilmente un'enorme quantità di spazio ed è difficile da manipolare quando si trova all'interno di una colonna di blob del database.

Uso i database per memorizzare nome, timestamp, metadati e posizione dei file. Quindi memorizzo e accedo all'immagine in quel file location/name

Ci sono passato qualche anno fa nel mondo reale e insieme a molti altri, sono giunto alla conclusione che archiviare le immagini nel database era un approccio sbagliato. Per il controllo delle versioni e la cronologia è sufficiente avere il codice con i riferimenti nel controllo del codice sorgente e gestirli come con qualsiasi altro. Quindi cambia il nome per ogni immagine, usa i timbri data e non riutilizzare esattamente lo stesso nome di file per un'altra immagine.

Molte persone che iniziano durante questo periodo devono eseguire il main switch dopo un po 'di tempo poiché il loro database diventa troppo grande a causa di tutte le immagini. Ciò ha un effetto a catena su esigenze di storage, server, CPU e, eventualmente, traffico di rete. Inoltre, rende più difficile l'utilizzo dello storage di file system basato su cloud che può tenere conto della posizione geografica, del traffico e simili. Queste tecniche diventano fondamentali man mano che la tua azienda cresce e avere le immagini in un database può limitare notevolmente le tue opzioni.

In conclusione, buono per piccoli progetti con una piccola quantità di dati di immagine. Non adatto per negozi più grandi o grandi quantità di dati.

    
risposta data 30.10.2014 - 01:44
fonte
3

Se si utilizza SQL Server (2008 o successivo), è possibile memorizzarli nel database come BLOB o utilizzando FILESTREAM. Come altri commentatori hanno sottolineato, non andrei con un negozio adeguato al file su approccio del disco in quanto dovrai gestire la coerenza in quello scenario.

Un buon link su FILESTREAM può essere trovato qui:

Linee guida FileStream

Alcune regole generali:

In SQL Server, BLOBs can be standard varbinary(max) data that stores the data in tables, or FILESTREAM varbinary(max) objects that store the data in the file system. The size and use of the data determines whether you should use database storage or file system storage. So, in a nutshell, these are the typical scenarios where this feature is best suited:

  • If you are storing BLOBs with an average size of 1MB or more.
  • When fast read access is adamant.
  • When you must access BLOBs from your application's middle tier code.

Overall, the main advantages of using FILESTREAM over other options are:

  • Storage and retrieval of BLOBs is made together with relational data in a single data store.
  • Yes, the BLOBs are included in database backups and restores.
  • Inserting, updating and deleting BLOBs and your relational data happens in the same database transaction.
  • The 2 GB max size for a varbinary(max) column does not apply; you are only limited by the available space on the NTFS file system.
  • The SQL Server buffer pool memory is not used to operate on BLOBs; in previous versions large BLOBs could consume a lot of this memory.
  • All BLOB access can be performed from .NET code, allowing your middle tier code to easily work with these objects.
  • The NTFS file system can save and retrieve large BLOBs more efficiently than SQL Server.

Still, a few restrictions apply to FILESTREAM implementations:

  • FILESTREAM feature is not supported with Database Mirroring.
  • FILESTREAM data containers cannot share the same directory or be nested.
  • FILESTREAM data is not encrypted even when transparent data encryption (TDE) is enabled.
    
risposta data 29.10.2014 - 22:23
fonte

Leggi altre domande sui tag