2009-03-19 6 views
36

Dies ist eine Frage, die zuvor gestellt wurde (large-text-and-images-in-sql), aber hauptsächlich für Daten, die geändert werden. In meinem Fall werden die Daten gespeichert und nie verändert. Es scheint nur vernünftig, alles zusammen zu halten.Würden Sie binäre Daten in der Datenbank oder im Dateisystem speichern?

Gibt es Gründe, warum ich statische binäre Daten nicht in einer Datenbank speichern sollte?

Angenommen, es ist eine vernünftige Sache zu tun, gibt es irgendwelche Vorteile für die Speicherung solcher Daten in separaten Tabellen? (Sie könnten jetzt erkennen, dass ich kein DB-Experte bin ...)

Klarstellen: Es wird wahrscheinlich nicht mehr als 10-20 Benutzer geben, aber diese werden in den USA und in Großbritannien sein. Die Binärdaten müssen in jedem Fall übertragen werden.

Antwort

32

Der Vorteil des Speicherns von Daten in der Datenbank besteht darin, DB-Sicherheitsmechanismen zu nutzen und Wartungskosten (Backups, ...) zu reduzieren. Der Nachteil besteht darin, die Belastung der Datenbank zu erhöhen und Verbindungen zu verbrauchen (was für lizenzierte Datenbankserver pro Verbindung teuer sein kann). Wenn Sie SQL Server 2008 verwenden, ist FILESTREAM eine gute Alternative.

Im Übrigen ist es für Web-Apps (oder andere Apps, die möglicherweise Daten streamen müssen) übrigens sinnvoller, Daten außerhalb von DB zu speichern.

+2

Ich bin nicht sicher, wie es Wartungs-/Backup-Kosten reduziert. Wenn überhaupt, erhöht es sie, weil das Sichern einer Datenbank im Allgemeinen kostspieliger und anspruchsvoller ist als das Sichern eines Dateisystems. Kannst du es ausarbeiten? – jrwren

+3

@jrwren Mein Punkt ist, dass Sie keine Dateien separat sichern und sie manuell synchronisieren müssen, um die Integrität der Daten in der Datenbanksicherung sicherzustellen. Je nach den Umständen kann es einfacher oder billiger sein. –

8

Der größte Nachteil beim Speichern von BLOBS ist der Speicherverbrauch. Können Sie sich vorstellen, was Select * from x für Tausende von Datensätzen mit einem 45k-Bild in jedem tun würde?

Wie Mehrdad sagte, gibt es auch Vorteile. Wenn Sie sich also für diesen Ansatz entscheiden, sollten Sie versuchen, Ihre Datenbank so zu gestalten, dass die meisten Abfragen mit BLOB-Daten in ihnen weniger Ergebnisse liefern. Vielleicht zum Beispiel machen Sie eins zu eins Beziehungen für diesen Zweck.

+0

+1 Guter Punkt - vielleicht ein guter Grund, Blobs in separate Tabelle zu setzen und über ID abzuholen? – paul

+0

Um ehrlich zu sein, ich hatte immer Angst, BLOB zu verwenden, weil ich sql saugen. Aber wenn ich muss, würde ich wahrscheinlich eine separate Eins-zu-Eins-Beziehung für jeden Blob machen. Ich benutze es ziemlich, da ich Verweise auf Dateien verwende. Außer diese würden in db gespeichert werden. Hinweis: Bitte tun Sie dies nicht in Webapps. – Vasil

+7

IMHO, es ist kein gültiges Argument. Doing 'select * from x' ist in den meisten Fällen eine schlechte Idee, mit der Ausnahme, dass Sie * jede * Spalte einer Tabelle in Ihrer App verwenden müssen. Das Einfügen von Blobs in eine separate Tabelle ist noch schlimmer, da Joins erforderlich sind und die Anfragen komplizierter werden. –

1

Ist das nicht genau das, was LOBs oder CLOBs oder .... entworfen wurden?

Wir haben CLOBs verwendet, um große Verschlüsselungen von Kreditkartentransaktionen für ein großes Airline-System zu speichern.

Speicherverbrauch ist jedoch Ihr größter Übeltäter.

HTH

prost,

5

Ich denke, das hängt von der Anwendung Ihres Gebäudes. Wenn Sie ein CMS-System erstellen und die Verwendung der Daten darin besteht, Bilder in einem Webbrowser anzuzeigen, kann es sinnvoll sein, die Bilder auf der Festplatte zu speichern und nicht in der Datenbank zu speichern. Obwohl ich ehrlich gesagt beides tun würde, was das Hinzufügen eines Servers zu einer Farm ermöglichen würde, ohne Dateien überall kopieren zu müssen.

Ein anderer Anwendungsfall kann ein komplexes Objekt sein, z. B. ein Workflow oder sogar ein Geschäftsobjekt mit vielen Interdependenzen. Sie können beide in ein binäres oder textbasiertes Format serialisieren und in der Datenbank speichern. Dann erhalten Sie den Vorteil der DB: ATOMIC, Backups, etc ...

Ich glaube nicht, dass Menschen select * Abfragen in erster Linie verwenden sollten. Was Sie tun, ist zwei Möglichkeiten, um die Daten zu erhalten, eine Methode gibt die Zusammenfassung Informationen zurück, die zweite würde den Blob zurückgeben. Ich kann mir nicht vorstellen, warum Sie Tausende von Bildern auf einmal zurückgeben müssen.

+0

+1 Für die Ideen. Über die Auswahl * von Teil. Sie müssen diese Abfrage nicht von Hand schreiben. Einige ORMs verwenden diese Art von Abfragen standardmäßig, also wenn jemand nicht vorsichtig ist ... autsch. – Vasil

+0

Heh, wissen Sie, welches ORM diese Abfragen verwendet? Ich möchte mich von ihnen fernhalten. nHibernate weiß ich nicht – JoshBerke

+0

Ich habe in einigen PHP-Framework gesehen, kann mich nicht erinnern. Aber da sie in einer Web-App sind, dachten sie wahrscheinlich, dass * weniger Daten über den Draht als wählen Foo, Bar, Wurst sind. Ich wette, sie haben nie an BLOBS gedacht. – Vasil

1

Einige Datenbank (z. B. Postgresql) automatisch Felder komprimieren, vielleicht ist es schneller beim Lesen sie direkt aus db.Außerdem kann das Programm alle Felder und Bilder auf einen Schlag lesen.

+1

Ja, wenn ich jemals Blobs benutzt hätte, wäre es Postgres. Sie sparen in der Bandbreite. Aber die Daten müssen irgendwann im Prozess der Anwendung unkomprimiert sein. – Vasil

+3

Viele Blobs (Bilder, MP3s, etc.) sind sowieso im Wesentlichen vorkomprimiert. – dkretz

2

Wir speichern Anhänge in unserem System, und Sie können einen Anhang nicht ändern, also ich denke, wir sind auf der gleichen Seite mit Daten, die "gespeichert und nie geändert werden." Wir entschieden uns ausdrücklich nicht, um es in der Datenbank zu speichern. Wir haben dies aus zwei Gründen getan, Einfachheit und Backup/Recovery-Zeit.

Einfachheit zuerst: In unserem Fall werden diese Anhänge vom Browser des Endbenutzers hochgeladen, und es ist einfacher, sie einfach in ein Verzeichnis (auf dem DB-Server) zu schreiben, als sie dann in die SQL-Pipe zu streamen. Es gibt eine Aufzeichnung von ihnen in der DB, aber die DB enthält nur Meta-Informationen über den Anhang und den Namen der Datei auf dem Datenträger (eine Guid in unserem Fall)

Auf der Backup/Recovery-Seite: Diese Blobs wird wahrscheinlich eines der größten Teile Ihrer Datenbank werden. Wenn Sie eine vollständige Sicherung ausführen, kopieren Sie diese Bits immer wieder, auch wenn Sie wissen, dass sie sich nie ändern können. Uns erschien es einfach viel einfacher, (viel) kleinere Backups zu haben, und eine Kopie des Anhangsverzeichnisses auf einem sekundären Server als Backup zu machen.

1

Das Leistungsproblem hier oben adressiert worden, also werde ich es nicht wiederholen. Aber ich denke, ein guter Tipp, wenn Sie Dinge speichern, die viel gestreamt werden (wie Bilder/Dokumente auf einer Website), ist in einem Caching-System zu bauen.

Damit meine ich speichern Sie alle Daten in Ihrer Datenbank, aber wenn jemand diese Datei anfordert, überprüfen Sie, ob es auf der Festplatte existiert (basierend auf einem bekannten Dateinamen, in einem Temp-Ordner), wenn nicht, greifen Sie es aus der DB Schreiben Sie sie in den Ordner und streamen Sie diese dann an den Benutzer. Für die nächste Anfrage an die gleiche Datei, da sie auf der Festplatte existiert, kann sie von dort aus bedient werden, ohne die DB zu treffen. Aber wenn Sie diese Dateien löschen müssen (oder Ihr Web-Server geht kapput!), Ist es egal, wie sie von der DB wieder aufgebaut werden, wie Leute sie anfordern. Dies sollte viel schneller sein als jede Anfrage für die gleiche Datei aus der DB zu bedienen.

4

Ich bin vertraut mit einem ziemlich großen OSS-Projekt, das die Entscheidung getroffen hat, Bilder in der MySQL-Datenbank zu speichern, und es gehört zu den 3 schlechtesten Ideen, mit denen sie seither fertig werden. (Verschärft durch die Tatsache, die „Refactoring gnadenlos“ Anathema ist, aber das ist eine andere Geschichte.)

Unter den ernsthaften Problemen dies verursacht hat:

  1. Überschreiten der maximalen effiziente Datenbankgröße (mysql). (Der für Bilder benötigte Gesamtraum übersteigt alle anderen um mindestens 2 Größenordnungen).

  2. Bilddateien verlieren ihre "Datei". Keine Datumsgrößen usw., wenn sie nicht (redundant) als Daten gespeichert werden (die Code für die Verwaltung erfordern).

  3. Beliebige Bytefolgen werden nicht ständig verarbeitet, weder zur Speicherung noch zur Bearbeitung.

  4. "Wir müssen nie extern auf die Bilder zugreifen" ist eine gefährliche Annahme.

  5. Zerbrechlichkeit. Weil die ganze Anordnung unnatürlich und empfindlich ist, und Sie nicht wissen, wo es als nächstes beißen wird (zur Anti-Refactor-Mentalität beitragend).

Die Vorteile? Keine, an die ich denken kann, außer dass es zu der Zeit der Weg des geringsten Widerstands war.

+0

Ich nehme an, die schlechte Entscheidung war, Blobs zu speichern. Richtig? – paul

+0

Richtig - geklärt. – dkretz

+1

Ein wesentlicher Vorteil ist die Konsistenz der Daten: Mit den richtigen Schlüsseln können die "Dateien" nicht ohne die Metadaten gelöscht werden und umgekehrt. Für Disk-Dateien gibt es keine solchen Einschränkungen und das Hinzufügen/Löschen der Dateien und ihrer Metadaten ist eine separate Anwendung (oder Funktion), die entworfen, implementiert und verwendet werden muss. – NVRAM

6

Um das Problem aus prinzipieller Sicht zu lösen, gibt es (hauptsächlich) eine relationale Datenbank zum Speichern strukturierter Daten. Wenn Sie keine Abfragebedingung oder Verknüpfung für ein Datenelement erstellen können, gehört es wahrscheinlich nicht in die Datenbank. Ich sehe kein Image-BLOB, das in einer WHERE-Klausel verwendet wird, also würde ich sagen, dass es außerhalb der Datenbank bleibt. Ein CLOB kann dagegen in Abfragen verwendet werden.

+0

+1 interessanter Aspekt – paul

+2

Wir werden wahrscheinlich nicht die Telefonnummer in einer WHERE-Klausel verwenden, da es überhaupt nicht häufig ist, nach einer Telefonnummer zu suchen (es sei denn, Sie arbeiten an einem Reverse-Lookup-System). Das heißt, wir speichern Telefonnummern in der Datenbank, nicht in externen Dateien, obwohl sie selten als Join- oder Filterbedingung verwendet wird. Was ich meine ist, dass dieser Grund nicht ausreicht, um die Möglichkeit, ein Bild in einer relationalen DB zu speichern, zu verwerfen. – Seb

+2

Aber * Sie * können eine Abfrage Bedingung für die Telefonnummer, oder verwenden Sie es für einen Beitritt, etwas, was Sie nicht vernünftigerweise mit einer BLOB-Spalte tun können. –

8

All das Gerede über eine "Auswahl * aus der Tabelle" verursacht große Speicher- und/oder Bandbreitenprobleme, wenn die Tabelle ein LOB enthält, ist kein Problem. Alles, was zurückgegeben wird, ist ein Zeiger auf das fragliche LOB. Nicht genug Reputation, um den Kommentar in den Kontext zu stellen, aber Leute, die darauf schauen, sollten wissen, dass es kein Problem ist.

+0

Was ist ein "LOB"? –

+0

@Matthew Ich denke, er meinte [Großes Objekt] (https://docs.oracle.com/cd/B28359_01/appdev.111/b28393/adlob_glossary.htm#sthref1212). –

3

Wer die Idee hatte, ein Bild (oder ein anderes binäres Dokument) in einer Datenbank zu speichern, ist nicht jemand, mit dem ich sehr zufrieden bin. Datenbanken sind für die Speicherung von [meistens?] INDEXABLE, DISCRETE Daten gedacht. Nicht BLOBs von bedeutungslosen binären Daten. Wenn Sie mit BLOBs für Binärdaten aus erster Hand gearbeitet haben, wissen Sie das bereits.

Sie sollten einen Verweis auf die Datei im Dateisystem speichern. Die beste Vorgehensweise ist ein Dateiname, kein absoluter (oder sogar relativer) Pfad.

+0

Soweit "SELECT *" geht, halte ich das in den meisten Fällen für sinnvoll. Ich habe ein ORM erstellt, das alles verwendet, aber Sie können das überschreiben. Und wenn Sie wirklich an der Leistung interessiert sind, können Sie das ORM vollständig umgehen und den Query Builder verwenden, den ORM im Hintergrund verwendet. Der Punkt ist, dass diese Konversation nichts mit "SELECT * ..." zu tun hat. Es hat mit Sound-Datenbank-Design zu tun. –

+0

Wie erhalten Sie Datei, wenn nur der Dateiname gespeichert ist nicht der Pfad? Hättest du einen Ordner, in dem alle Dateien abgelegt würden? Was ist, wenn Millionen von Dateien in meiner Datenbank vorhanden sind? – Vincnetas

+0

In der Config irgendwo in der Anwendung sollten Sie den Pfad zu dem Verzeichnis speichern, in dem die Dateien gespeichert sind. Wenn Sie Bedenken haben, zu viele Dateien im selben Verzeichnis zu haben, erstellen Sie den Pfad dynamisch. Normalerweise können Sie dafür eine ID verwenden, wie/path/to/files/{ID here}/Dateiname.ext. Sie müssen nur den Dateinamen speichern. –

Verwandte Themen