it-swarm.com.de

Ist es eine schlechte Praxis, große Dateien (10 MB) in einer Datenbank zu speichern?

Ich erstelle derzeit eine Webanwendung, mit der Benutzer Dateien mit einer Größe von 1 bis 10 MB speichern und freigeben können.

Es scheint mir, dass das Speichern der Dateien in einer Datenbank den Datenbankzugriff erheblich verlangsamen wird.

Ist das ein berechtigtes Anliegen? Ist es besser, die Dateien im Dateisystem zu speichern und den Dateinamen und den Pfad in der Datenbank zu speichern? Gibt es Best Practices zum Speichern von Dateien beim Arbeiten mit einer Datenbank?

Ich arbeite in PHP und MySQL für dieses Projekt, aber das Problem ist für die meisten Umgebungen dasselbe ( Ruby on Rails , ). PHP , . NET ) und Datenbanken (MySQL, PostgreSQL ).

202
B Seven

Gründe für das Speichern von Dateien in der Datenbank :

  1. ACID-Konsistenz, einschließlich eines Rollbacks eines Updates, das kompliziert ist, wenn die Dateien außerhalb der Datenbank gespeichert werden. Dies ist nicht leicht zu beschönigen. Es kann sehr nützlich sein, die Dateien und die Datenbank synchron zu halten und an Transaktionen teilnehmen zu können.
  2. Dateien gehören zur Datenbank und können nicht verwaist werden.
  3. Backups enthalten automatisch die Datei-Binärdateien.

Grund gegen das Speichern von Dateien in der Datenbank :

  1. Die Größe einer Binärdatei unterscheidet sich zwischen den Datenbanken. Wenn Sie unter SQL Server beispielsweise das FILESTREAM-Objekt nicht verwenden, sind es 2 GB. Wenn Benutzer größere Dateien speichern müssen (z. B. einen Film), müssen Sie durch die Rahmen springen, um diese Magie zu verwirklichen.
  2. Erhöht die Größe der Datenbank. Ein allgemeines Konzept, das Sie sich zu Herzen nehmen sollten: Der für die Pflege einer Datenbank erforderliche Wissensstand steigt proportional zur Größe der Datenbank. Dh groß Datenbanken sind komplizierter zu pflegen als kleine Datenbanken. Durch das Speichern der Dateien in der Datenbank kann die Datenbank viel größer werden. Selbst wenn beispielsweise eine tägliche vollständige Sicherung bei einer größeren Datenbankgröße ausgereicht hätte, ist dies möglicherweise nicht mehr möglich. Möglicherweise müssen Sie in Betracht ziehen, die Dateien in eine andere Dateigruppe zu stellen (sofern die Datenbank dies unterstützt), die Sicherungen zu optimieren, um die Sicherung der Daten von der Sicherung der Dateien usw. zu trennen. Keines dieser Dinge ist unmöglich zu lernen, aber zu tun Erhöhen Sie die Komplexität der Wartung, was Kosten für das Unternehmen bedeutet. Größere Datenbanken verbrauchen auch mehr Speicher, da sie versuchen, so viele Daten wie möglich in den Speicher zu packen.
  3. Portabilität kann ein Problem sein, wenn Sie systemspezifische Funktionen wie das SQL Server-Objekt FILESTREAM verwenden und auf ein anderes Datenbanksystem migrieren müssen.
  4. Der Code, der die Dateien in die Datenbank schreibt, kann ein Problem sein. Ein Unternehmen, für das ich vor nicht allzu vielen Monden konsultiert habe, hat irgendwann ein Microsoft Access-Frontend mit seinem Datenbankserver verbunden und die Fähigkeit von Access verwendet, "alles" mithilfe des Ole Object-Steuerelements hochzuladen. Später wechselten sie zu einer anderen Steuerung, die sich immer noch auf Ole stützte. Viel später änderte jemand die Schnittstelle, um die rohe Binärdatei zu speichern. Das Extrahieren dieser Ole-Objekte war eine neue Ebene der Hölle. Wenn Sie Dateien im Dateisystem speichern, ist keine zusätzliche Ebene zum Umschließen/Optimieren/Ändern der Quelldatei erforderlich.
  5. Es ist komplizierter, die Dateien auf einer Website bereitzustellen. Um dies mit Binärspalten zu tun, müssen Sie einen Handler schreiben, um die Binärdatei aus der Datenbank zu streamen. Sie können dies auch tun, wenn Sie Dateipfade speichern, dies jedoch nicht tun müssen. Auch hier ist das Hinzufügen eines Handlers nicht unmöglich, erhöht jedoch die Komplexität und ist ein weiterer Fehlerpunkt.
  6. Sie können den Cloud-Speicher nicht nutzen. Angenommen, Sie möchten eines Tages Ihre Dateien in einem Amazon S3-Bucket speichern. Wenn Sie in der Datenbank Dateipfade speichern, können Sie diese in S3 in Pfade ändern. Soweit mir bekannt ist, ist dies in keinem Szenario mit einem DBMS möglich.

IMO erfordert die Speicherung von Dateien in der Datenbank oder nicht als "schlecht" mehr Informationen über die Umstände und Anforderungen. Werden die Größe und/oder Anzahl der Dateien immer klein sein? Gibt es keine Pläne für die Verwendung von Cloud-Speicher? Werden die Dateien auf einer Website oder einer ausführbaren Binärdatei wie einer Windows-Anwendung bereitgestellt?

Im Allgemeinen hat meine Erfahrung gezeigt, dass das Speichern von Pfaden für das Unternehmen kostengünstiger ist, selbst wenn der Mangel an Säure und die Möglichkeit von Waisenkindern berücksichtigt werden. Dies bedeutet jedoch nicht, dass das Internet keine Legion von Berichten über mangelnde ACID-Kontrolle ist, die beim Speichern von Dateien schief gehen, sondern dass diese Lösung im Allgemeinen einfacher zu erstellen, zu verstehen und zu warten ist.

145
Thomas

In vielen Fällen ist dies eine schlechte Idee. Dadurch werden die Datenbankdateien aufgebläht und es treten verschiedene Leistungsprobleme auf. Wenn Sie das Blobs in eine Tabelle mit einer großen Anzahl von Spalten stecken, ist es noch schlimmer.

Jedoch! Einige Datenbanken wie SQL Server haben einen FILESTREAM-Spaltentyp. In diesem Fall werden Ihre Daten tatsächlich in einer separaten Datei auf dem Datenbankserver gespeichert und nur eine ID der Datei wird in der Tabelle gespeichert. In diesem Fall sehe ich keinen Grund, die Daten nicht im SQL Server zu speichern. Die Dateien werden automatisch in die Serversicherung einbezogen, und die Datenbank und die Dateien sind nie nicht synchron. Das Problem mit Tonys Vorschlag, Dateinamen zu speichern, besteht darin, dass die Datenbank und das Dateisystem möglicherweise nicht mehr synchron sind. Die Datenbank behauptet, dass eine Datei vorhanden ist, wenn sie auf der Festplatte gelöscht wurde. Wenn ein Prozess die Datenbank ändert und dann abstürzt, stimmen die Dateien und die Datenbank nicht überein (d. H. Nein ACID mit Dateien außerhalb einer Datenbank).

93

Ja, das ist eine schlechte Praxis.

Auswirkungen auf die Leistung der Datenbank:

  • wenn Sie ein SELECT mit einer BLOB-Spalte ausführen, führen Sie immer einen Datenträgerzugriff durch, während Sie ohne BLOBs eine Chance haben Daten direkt von RAM (DB mit hohem Durchsatz wird optimiert, um Tabellen in RAM zu passen);
  • die Replikation ist langsam, die Replikationsverzögerung hoch, da BLOB an Slaves gesendet werden muss. Eine hohe Replikationsverzögerung führt zu allen Arten von Rennbedingungen und anderen Synchronisationsproblemen, sofern Sie dies nicht ausdrücklich berücksichtigen.
  • DB-Backups/Wiederherstellungen dauern viel länger.

Geschwindigkeitsvorteil - keine ! Während einige ältere Dateisysteme Verzeichnisse mit Millionen von Dateien nicht gut verarbeiten würden, haben die meisten modernen überhaupt keine Probleme und verwenden tatsächlich die gleichen Datenstrukturen wie BDs (normalerweise B-Bäume). Zum Beispiel verwendet ext4 (Standard-Linux-Dateisystem) Htree .

Schlussfolgerung: Dies beeinträchtigt die Leistung Ihrer Datenbank und verbessert nicht die Leistung beim Abrufen von Dateien.

Da es sich um eine Webanwendung handelt, ist das Bereitstellen statischer Dateien direkt aus dem Dateisystem mithilfe eines modernen Webservers, der sendfile() syscall ausführen kann, enorm Leistungsverbesserung. Dies ist natürlich nicht möglich, wenn Sie Dateien aus der Datenbank abrufen. Betrachten Sie zum Beispiel diesen Benchmark , der zeigt, dass Ngnix 25K-Anforderungen mit 1000 gleichzeitigen Verbindungen auf einem Low-End-Laptop ausführt. Diese Art von Ladung würde jede Art von DB braten.

36
vartec

Ich wäre pragmatisch und folge dem Prinzip "Noch nicht optimieren". Machen Sie die Lösung, die im Moment sinnvoll ist und für die Sie die Entwicklungsressourcen haben, um sie ordnungsgemäß zu implementieren. Es gibt viele mögliche Probleme. Aber diese werden nicht unbedingt zu echten Problemen. Z.B. Es wäre wahrscheinlich kein Problem, wenn Sie 100 Benutzer haben. Es kann ein Problem sein, wenn Sie 100.000 oder 10.000.000 Benutzer haben. Im letzteren Fall sollte es jedoch eine Grundlage für mehr Entwicklungsressourcen geben, um alle Probleme zu lösen.

Das Speichern der Daten in der Datenbank entlastet Sie jedoch von anderen Problemen, z. Wo sollen die Dateien gespeichert werden, wie sollen sie gesichert werden usw. Da Sie eine Webanwendung schreiben, ist es aus Sicherheitsgründen eine sehr gute Idee, sicherzustellen, dass der Prozess, der die Anwendung hostet, keinen Schreibzugriff auf die Datei hat Daher müssen Sie den Server so konfigurieren, dass der Prozess Lese-/Schreibzugriff auf den Ordner hat, in dem die Daten gespeichert sind.

Ich würde mich persönlich dafür entscheiden, die Daten in der Datenbank zu speichern, aber sicherstellen, dass die BLOBS erst gelesen werden, wenn sie wirklich benötigt werden, d. H. Kein "SELECT * FROM ...", das in den Tabellen ausgeführt wird, die Blogs enthalten. Und ich würde sicherstellen, dass das Design es einfach macht, die Daten aus der Datenbank in das Dateisystem zu verschieben, wenn Sie Leistungsprobleme haben. Speichern Sie beispielsweise die Dateiinformationen in einer separaten Datei , um die Dateiinformationen von anderen Geschäftseinheiten fernzuhalten.

Angenommen, Sie haben eine File - Klasse zur Darstellung einer in der Datenbank gelesenen Datei, dann ist die Codierungswirkung eines späteren Verschiebens minimal.

21
Pete

Microsoft hat vor einigen Jahren ein Whitepaper dazu veröffentlicht. Es konzentriert sich auf SqlServer, aber Sie können dort einige interessante Informationen finden:

Zu BLOB oder nicht zu BLOB? Großer Objektspeicher in einer Datenbank oder einem Dateisystem?

Eine sehr prägnante Version ihrer Schlussfolgerung lautet:

Beim Vergleich des NTFS-Dateisystems mit SQL Server 2005 werden BLOBS mit weniger als 256 KB von SQL Server effizienter verarbeitet, während NTFS für BLOBS mit mehr als 1 MB effizienter ist.

Ich würde empfehlen, dass Sie einige kleine Tests für Ihren speziellen Anwendungsfall schreiben. Denken Sie daran, dass Sie sich vor Caching-Effekten hüten müssen. (Ich war erstaunt, als ich zum ersten Mal Speichergeschwindigkeit auf der Festplatte erhielt, die einen höheren Durchsatz zu haben schien, als physikalisch möglich war!)

16
Benjol

Die alte konventionelle Weisheit, Dateien außerhalb der Datenbank zu speichern, ist möglicherweise nicht mehr gültig. Grundsätzlich würde ich Integrität der Geschwindigkeit vorziehen, und mit einem modernen DBMS können Sie beides haben.

Tom Kyte scheint einverstanden :

Ich kenne keine Vorteile beim Speichern von Daten, die ich für eine lange Zeit außerhalb einer Datenbank aufbewahren möchte.

Wenn es in der Datenbank ist, kann ich

stellen Sie sicher, dass es professionell verwaltet wird

gesichert

wiederherstellbar (mit dem Rest der Daten)

gesichert

skalierbar (versuchen Sie, 100.000 Dokumente in einem einzigen Verzeichnis abzulegen, und legen Sie sie jetzt in einer Tabelle ab - welche "skaliert" - es ist nicht das Verzeichnis)

Ich kann leicht wiederherstellen (Rückblende)

Ich habe Sperren

Ich habe Konsistenz gelesen ...

11

Ja.

Wenn Sie eine Datei aus Ihrem Dateisystem bereitstellen, kann Ihr Webserver Kernelcode wie sendfile () unter BSD oder Linux verwenden, um die Datei direkt in den Socket zu kopieren. Es ist sehr schnell und sehr effizient.

Das Bereitstellen von Dateien aus der Datenbank bedeutet, dass Sie Daten von der Festplatte des Datenbankservers in den Speicher des Datenbankservers kopieren müssen, dann vom Speicher des Datenbankservers zum Netzwerkport des Datenbankservers, dann vom Netzwerk zu Ihrem Webserverprozess und dann wieder zum ausgehende Netzwerkverbindung.

Wenn Sie keinen guten Grund haben, dies nicht zu tun, ist es immer besser, statische Dateien aus dem Dateisystem bereitzustellen.

8
Evan P.

Der berühmte Tom Kyte hat geschrieben, dass sie (das Oracle) die Oracle-Datenbank als Dateiserver verwenden und sie einwandfrei funktioniert, sogar schneller als das normale Dateisystem, mit voller Transaktionalität, ohne Leistungsverlust und mit einer einzigen Sicherung.

Ja, aber beachten Sie, dass sie der Hersteller der Oracle-Datenbank sind und für jeden anderen Benutzer Kostenprobleme auftreten. Die Verwendung einer kommerziellen Datenbank wie Oracle zum Speichern von Dateien ist einfach kostengünstig.

Mit PostgreSQL können Sie jedoch einfach eine andere DB-Instanz nur für den Blob-Speicher ausführen. Sie haben dann volle Transaktionsunterstützung. Die Transaktionsfähigkeit kostet jedoch DB-Speicherplatz. Die Datenbank muss mehrere Blob-Instanzen für mehrere gleichzeitige Transaktionen speichern. Unter PostgreSQL ist dies am schmerzhaftesten, da in dieser Datenbank die Duplikate der für die Transaktion erstellten Blobs gespeichert werden, auch wenn sie nicht mehr benötigt werden, bis der VACUUM-Prozess abgeschlossen ist.

Beim Speichern von Dateisystemen müssen Sie dagegen sehr vorsichtig sein, wenn jemand die Datei ändert, da die Transaktion zurückgesetzt werden kann und die Kopie der Datei aufbewahrt werden muss, bis die alte Version nicht mehr sichtbar ist.

In dem System, in dem Dateien nur hinzugefügt und gelöscht werden und der Transaktionszugriff auf Dateien kein Problem darstellt, ist der Dateisystemspeicher meiner Meinung nach die beste Wahl.

5
Danubian Sailor

Normalerweise ist es am besten, große BLOBs in einer separaten Tabelle zu speichern und einfach einen Fremdschlüsselverweis auf das BLOB in Ihrer Haupttabelle zu behalten. Auf diese Weise können Sie die Datei weiterhin aus der Datenbank abrufen (Sie benötigen also keinen speziellen Code) und vermeiden die Probleme im Zusammenhang mit externen DB-Abhängigkeiten (Synchronisierung von DB und Dateisystem usw.), verursachen jedoch nur diesen Overhead wenn Sie explizit dieser Tabelle beitreten (oder einen separaten Aufruf tätigen). 10 MB sind nicht besonders groß, die meisten modernen kommerziellen Datenbanken haben kein Problem. Der einzige Grund, warum ich eine Datei im Dateisystem speichern würde, ist die Reduzierung der Datenbankbandbreite. Wenn Ihre Datenbank viele dieser Dateien mischen soll, müssen Sie möglicherweise die Arbeitslast aufteilen und nur eine Art Dateideskriptor speichern. Anschließend können Sie die Datei separat aufrufen, um sie von einem anderen Server zu laden, damit Sie Ihre Datenbankverbindungen (und Netzwerkverbindungen auf Ihrem Datenbankserver) nicht mit all diesen Dateiübertragungen verknüpfen.

5
TMN

Möglicherweise treten einige dieser Probleme auf:

  • Das Ausführen eines SELECT *, Bei dem die Zeile mit dem großen Blob verwendet wird, dauert sehr lange, auch wenn Sie den Blob nicht benötigen (Natürlich sollten Sie eine bestimmte Auswahl treffen, aber manchmal werden Anwendungen so geschrieben).
  • Das Erstellen eines Backups kann viel länger dauern. Abhängig von Ihren Anforderungen müssen Sie möglicherweise Ihre Tabellen für die Zeit der Sicherung sperren, sodass Sie Ihre Sicherungszeit möglicherweise niedrig halten möchten
  • Das Wiederherstellen dauert auch viel länger.
  • Wenn Ihnen der Speicherplatz ausgeht, müssen Sie sich überlegen, wie Sie dieses Problem lösen können (möglicherweise die gesamte Datenbank auf einen neuen Server verschieben). Wenn Sie die Dateien im Dateisystem speichern, können Sie jederzeit eine andere Festplatte bereitstellen und Softlinks festlegen.
  • Das einfache Durchsuchen einer Datei zum Debuggen oder für andere Informationen ist nicht so einfach. Dies schließt auch Skripte ein, die möglicherweise keinen Zugriff auf die Datenbank haben, jedoch einige Informationen aus verschiedenen Dateien benötigen.

Natürlich erhalten Sie auch einige Vorteile:

  • Sichern von Daten und Dateimenüs, die synchron sind
  • Das Entfernen der Datei ohne Kenntnis der Datenbank ist nicht möglich
  • Sie müssen die Datei nicht von der Festplatte lesen, sondern können dies in einer SQL-Anweisung tun
  • Sie können die Datenbank herunterladen, den Speicherauszug in Ihre Entwicklungsumgebung aufnehmen und alle Abhängigkeiten direkt dort haben

Persönlich mache ich das nicht, da ich die Nachteile viel schwerer finde als die Vorteile. Aber wie oben erwähnt, hängt es völlig von Ihrem Anwendungsfall und dergleichen ab.

4
Sgoettschkes

Einige Enterpirse Content Management-Systeme wie SiteCore verwenden eine Datenbank zum Speichern von Seitendaten und eine andere Datenbank zum Speichern von Dateien. Sie verwenden MS SQL Server.

1
šljaker

Für die praktische Umsetzung können Sie Folgendes beachten:

Vorteile :

  1. Alle Dateiinhalte werden definitiv mit Ihrer Tabelle synchronisiert. Wie oben erwähnt, ist das Sichern von Daten äußerst praktisch, da Sie die Daten nicht mit dem Dateisystem synchronisieren müssen.
  2. Durch Codierung können Sie Dateiinhalte direkt aus einer SQL-Auswahl abrufen.
  3. Aus einer Abfrage können Sie sogar den Dateiinhalt oder seine Größe explizit aus der SQL-Anweisung herausfiltern.

Nachteile :

  1. Im Vergleich zu einer Datenbank, deren Struktur semantisch identisch ist, jedoch keinen Dateiinhalt speichert, verbraucht Ihre Datenbank bei der Abfrage tendenziell radikal mehr Speicher.
  2. Automatische Sicherung kann Leistungsprobleme verursachen, aber nicht viel. Stellen Sie sich vor, Ihr Datenbankserver sichert alle 6 Stunden Daten und in Ihren Datenbanken werden 10-MB-Dateien pro Datensatz gespeichert. Dieses Szenario ist nicht das, was Sie wollen.
1

Dies ist einer der folgenden Punkte: "Kann ich einen Apfel mit einer Rasierklinge aufschneiden?" Ja, du kannst.

Solltest du? Wer soll das sagen ...

Ich denke, wenn Sie sich in einer Situation befinden, in der Ihr Werkzeug dies zulässt oder das einzige verfügbare Werkzeug ist (zumindest, um diese Frist zu erreichen). Zum Beispiel habe ich einen flachen Schraubendreher verwendet, um einen Philips-Bolzentyp zu entfernen ... war das richtig? War das das richtige Werkzeug? War es eine schlechte Wahl?

Die Antwort auf diesen Fall lautet: Die Datenbank soll keine Dateien speichern ... wenn Sie es falsch machen, hätte ich theoretisch nicht den flachen Schraubendreher zum Entfernen der Philips-Schraube verwenden sollen, da ich dabei verloren habe Der Vorteil, dass der Philips-Schraubendreher nicht fehl am Platz ist und alles beschädigt, woran ich gerade arbeite (da Sie die Vorteile verlieren würden, wenn Sie eine Datenbank als Dateispeicherlösung verwenden) ... dennoch habe ich das Risiko richtig berechnet und alles lief einwandfrei.

wenn Sie die Dinge richtig machen möchten, sollten Sie wahrscheinlich git verwenden, um Ihre Dateien zu speichern, und einfach die erforderlichen Git-Hashes in Ihrer Datenbank behalten, um auf die richtige Dateiversion zu verweisen, die Sie benötigen ... genauso wie ich zu meinem Tool gehen konnte Box und hol den verdammten Philips Schraubenzieher ...

0
Ordiel