2015-03-26 13 views
12

Per semplicità, supponiamo di sviluppare un'app mobile come Instagram. Gli utenti possono scaricare immagini dal server e caricare le proprie immagini. Attualmente il server memorizza tutte le immagini (in realtà, solo piccole miniature) in un database MySQL come BLOB. Sembra che il modo più comune per trasferire le immagini sia utilizzando la codifica Base64, che mi lascia con due opzioni:MySQL - Base64 vs BLOB

  1. Il server memorizza tutte le immagini come BLOB. Per caricare un'immagine, il client lo codifica nella stringa Base64, quindi lo invia al server. Il server decodifica l'immagine BACK in formato binario e la memorizza come BLOB nel database. Quando il client richiede un'immagine, il server ricodifica l'immagine come stringa Base64 e la invia al client, che la decodifica nuovamente in binario per la visualizzazione.
  2. Il server memorizza tutte le immagini come stringhe Base64. Per caricare un'immagine, il client lo codifica nella stringa Base64 e lo invia al server. Il server non esegue alcuna codifica o decodifica, ma semplicemente memorizza la stringa nel database. Quando il client richiede un'immagine, la stringa Base64 viene restituita al client, che quindi la decodifica per la visualizzazione.

Chiaramente, l'opzione # 1 richiede un'elaborazione significativamente maggiore sul server, poiché le immagini devono essere codificate/decodificate con ogni singola richiesta. Ciò mi spinge verso l'opzione n. 2, ma alcune ricerche hanno suggerito che l'archiviazione della stringa Base64 in MySQL è molto meno efficiente rispetto all'archiviazione dell'immagine direttamente come BLOB ed è generalmente scoraggiata.

Non sono certo il primo ad incontrare questa situazione, quindi qualcuno ha suggerimenti sul modo migliore per farlo funzionare?

+2

L'opzione n. 3 non contiene immagini nel database. Hanno un sistema per questo: il filesystem. – tadman

+0

Ho iniziato a memorizzare i percorsi dei file, ma alcune ricerche sulle versioni più recenti di MySQL hanno suggerito che è in realtà più efficiente memorizzare piccoli file (sotto 1 o 2 mb) come BLOB. Le mie immagini sono solo pochi kb, quindi è molto più semplice mantenere questo modo. – hundley

+0

Il backup di un database pieno di BLOB è un vero incubo. È costoso replicare questi, costosi per sostenerli, estremamente doloroso per ripristinarli, e straziante per dividerli quando diventano troppo grandi. A meno che tu non abbia a che fare con quantità insignificanti di dati, alla fine questo esploderà. I file su disco possono essere replicati facilmente usando qualcosa di rudimentale come 'rsync'. Lo stesso non è vero per MySQL. – tadman

risposta

5

JSON assume utf8, quindi è incompatibile con le immagini a meno che non siano codificate in qualche modo.

Base64 è quasi esattamente 8/6 volte più voluminoso di binario (BLOB). Si potrebbe sostenere che è facilmente accessibile. 3000 bytes diventa circa 4000 bytes.

Tutti devono essere in grado di accettare codici a 8 bit arbitrari, ma non tutti lo fanno. Base 64 può essere il miglior compromesso più semplice e complessivo per non dover gestire i dati a 8 bit.

Poiché questi sono "piccoli", li memorizzerei in una tabella, non in un file. Vorrei, tuttavia, memorizzarli in una tabella separata e JOIN da un appropriato id quando ne hai bisogno. Ciò consente alle query che non richiedono l'esecuzione dell'immagine più veloce perché non passano sopra i BLOB.

Tecnicamente, TEXT CHARACTER SET ascii COLLATE ascii_bin farebbe, ma BLOB rende più chiaro che non c'è davvero alcun testo utilizzabile nella colonna.

+0

Per chiarire, stai suggerendo di archiviare le immagini come Base64 in un BLOB, o i dati binari stessi e codificare su ogni fetch? Per quanto riguarda il tuo suggerimento con JOINing - questo è esattamente quello che sto facendo, insieme a un indice Sphinx. – hundley

+0

Base64 per tutta la sua durata. Quindi non è necessario eseguire la fuga da nessuna parte. Quindi, sì, Base64 in un BLOB senza codifica tranne nell'INSERTO iniziale. Questa è la mia opinione_. –

+0

Interessante, forse darò uno scatto. Sarebbe sicuramente risparmiare un sacco di CPU dato che i recuperi avvengono molto più spesso degli inserti. – hundley

1

Perché dovresti codificare in base64 le immagini sul filo? Penso che tu stia fissando un'ipotesi sbagliata.

+0

Potrebbe chiarire? In questo momento sto inviando tutte le immagini come oggetti JSON con codifica Base64, con alcuni metadati (quindi il client sa cosa fare con l'immagine al momento del ricevimento). C'è un modo per inviare le immagini come oggetti binari (nessuna codifica) CON i metadati? Che dire del client POST di una nuova immagine? Il mio server utilizza Node.js con Express per HTTP, nonché [ws] (https://github.com/websockets/ws) per alcune funzionalità di WebSocket. – hundley