Ich erstelle gerade eine Webanwendung, mit der Benutzer Dateien mit einer Größe von 1 MB bis 10 MB speichern und freigeben können.
Mir scheint, dass das Speichern der Dateien in einer Datenbank den Datenbankzugriff erheblich verlangsamt.
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 für das Speichern von Dateien beim Arbeiten mit einer Datenbank?
Ich arbeite in PHP und MySQL für dieses Projekt, aber es ist das gleiche Problem für die meisten Umgebungen ( Ruby on Rails , PHP , .NET ) und Datenbanken (MySQL, PostgreSQL ).
database
database-design
mysql
file-handling
B Sieben
quelle
quelle
10MB
in einem modernen System nicht so groß sehe .Antworten:
Gründe für das Speichern von Dateien in der Datenbank:
Grund gegen das Speichern von Dateien in der Datenbank:
FILESTREAM
Objekt von SQL Server verwenden und auf ein anderes Datenbanksystem migrieren müssen.IMO erfordert mehr Informationen über die Umstände und Anforderungen, wenn die Speicherung von Dateien in der Datenbank als "schlecht" oder nicht als "schlecht" eingestuft wird. 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?
Generell habe ich die Erfahrung gemacht, dass das Speichern von Pfaden für das Unternehmen kostengünstiger ist, selbst wenn das Fehlen von ACID und die Möglichkeit von Waisen berücksichtigt werden. Dies bedeutet jedoch nicht, dass das Internet keine Legion mit Berichten über mangelnde ACID-Kontrolle ist, die beim Speichern von Dateien schief gehen. Es bedeutet jedoch, dass diese Lösung im Allgemeinen einfacher zu erstellen, zu verstehen und zu warten ist.
quelle
In vielen Fällen ist dies eine schlechte Idee. Es wird die Datenbankdateien aufblähen und mehrere Leistungsprobleme verursachen. Wenn Sie die Blobs in eine Tabelle mit einer großen Anzahl von Spalten stecken, ist es noch schlimmer.
Jedoch! Einige Datenbanken, z. B. SQL Server, haben den Spaltentyp FILESTREAM. In diesem Fall werden Ihre Daten tatsächlich in einer separaten Datei auf dem Datenbankserver gespeichert, und in der Tabelle wird nur eine ID für die Datei gespeichert. In diesem Fall sehe ich kaum einen Grund, die Daten nicht im SQL Server zu behalten. Die Dateien werden automatisch als Teil der Serversicherung einbezogen, und die Datenbank und die Dateien sind nie nicht synchron. Das Problem mit Tonys Vorschlag, Dateinamen zu speichern, ist, dass die Datenbank und das Dateisystem 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 (dh keine ACID mit Dateien außerhalb einer Datenbank).
quelle
Ja, das ist eine schlechte Praxis.
Leistungseinflüsse auf die DB:
SELECT
mit einer BLOB-Spalte ausführen, wird immer auf die Festplatte zugegriffen, während Sie ohne BLOBs die Möglichkeit haben, Daten direkt aus dem RAM abzurufen (die DB mit hohem Durchsatz wird so optimiert, dass sie Tabellen in den RAM einfügt).Geschwindigkeitsvorteil - keiner ! Während einige ältere Dateisysteme Verzeichnisse mit Millionen von Dateien nicht gut handhaben würden, haben die meisten modernen überhaupt kein Problem und verwenden tatsächlich dieselbe Art von Datenstrukturen wie BDs (typischerweise B-Bäume). Zum Beispiel verwendet ext4 (Standard-Linux-Dateisystem) Htree .
Fazit: 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, eine enorme Leistungsverbesserung. Dies ist natürlich nicht möglich, wenn Sie Dateien aus der DB abrufen. Betrachten Sie zum Beispiel diesen Benchmark , in dem Ngnix 25 KBit / s mit 1000 gleichzeitigen Verbindungen auf einem Low-End-Laptop ausführt . Diese Art von Ladung würde jede Art von DB braten.quelle
Ich wäre pragmatisch und würde dem Prinzip "noch nicht optimieren" folgen. Entscheiden Sie sich für eine Lösung, die im Moment Sinn macht und für die Sie die Entwicklungsressourcen haben, die Sie ordnungsgemäß implementieren können. Es gibt viele mögliche Probleme . Aber diese werden nicht unbedingt zu echten Problemen. ZB wäre es wahrscheinlich kein Problem, wenn Sie 100 Benutzer haben. Es könnte 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 nicht von anderen Problemen, z. B. wo die Dateien gespeichert werden sollen, wie sie gesichert werden sollen usw. Da Sie eine Webanwendung schreiben, ist dies aus Sicherheitsgründen eine sehr gute Idee Um sicherzustellen, dass der Prozess, der die Anwendung hostet, keinen Schreibzugriff auf das Dateisystem hat, müssen Sie den Server so konfigurieren, dass der Prozess Lese- / Schreibzugriff auf den Ordner hat, in dem die Daten gespeichert sind.
Ich persönlich würde wählen, die Daten in der Datenbank zu speichern, aber sicherstellen, dass die BLOBS nicht gelesen werden, bis sie wirklich benötigt werden, dh kein "SELECT * FROM ..." für die Tabellen, 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 Leistungsprobleme auftreten. Speichern Sie beispielsweise die Dateiinformationen in einer separaten Dateitabelle , um die Dateiinformationen von anderen Unternehmenseinheiten fernzuhalten.
Angenommen, Sie haben eine File- Klasse zum Darstellen einer in der Datenbank gelesenen Datei, dann ist der Codierungsaufwand beim späteren Verschieben minimal.
quelle
Microsoft hat dazu vor einigen Jahren ein Whitepaper veröffentlicht. Es konzentriert sich auf SqlServer, aber Sie können einige interessante Informationen darin finden:
Eine sehr knappe Fassung ihrer Schlussfolgerung lautet:
Ich würde empfehlen, dass Sie einige kleine Tests für Ihren speziellen Anwendungsfall schreiben. Denken Sie daran, dass Sie auf Caching-Effekte achten müssen. (Ich war erstaunt, als ich zum ersten Mal Speicherkapazitäten bekam, die einen höheren Durchsatz zu haben schienen, als dies physikalisch möglich war!)
quelle
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 zuzustimmen :
quelle
Ja.
Wenn Sie eine Datei aus Ihrem Dateisystem bereitstellen, kann Ihr Webserver Kernel-Code wie sendfile () unter BSD oder Linux verwenden, um die Datei direkt in den Socket zu kopieren. Es ist sehr schnell und sehr effizient.
Wenn Sie Dateien aus der Datenbank bereitstellen, müssen Sie Daten von der Festplatte des Datenbankservers in den Speicher des Datenbankservers kopieren, dann vom Speicher des Datenbankservers in den Netzwerkport des Datenbankservers, dann vom Netzwerk in den Webserverprozess und dann wieder in den ausgehende Netzwerkverbindung.
Sofern Sie keinen guten Grund haben, dies nicht zu tun, ist es immer besser, statische Dateien aus dem Dateisystem bereitzustellen.
quelle
Der berühmte Tom Kyte hat geschrieben, dass sie (das Oracle) die Oracle-Datenbank als Dateiserver verwenden und dass sie einwandfrei funktioniert, sogar schneller als das normale Dateisystem, mit vollständiger Transaktionalität, ohne Leistungsverlust und mit einer einzelnen Sicherung.
Ja, aber beachten Sie, dass sie der Hersteller der Oracle-Datenbank sind und für alle anderen Benutzer Kostenprobleme auftreten. Kommerzielle Datenbanken wie Oracle für die Speicherung von Dateien zu verwenden, ist einfach ineffektiv.
Mit PostgreSQL zum Beispiel können Sie jedoch einfach eine andere DB-Instanz nur zum Speichern von Blobs ausführen. Sie haben dann volle Transaktionsunterstützung. Die Transaktionalität kostet jedoch Speicherplatz in der Datenbank. 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.
Andererseits müssen Sie beim Speichern von Dateisystemen 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 transaktionale Zugriff auf Dateien kein Problem darstellt, ist der Dateisystemspeicher meiner Meinung nach die beste Wahl.
quelle
In der Regel ist es am besten, große BLOBs in einer separaten Tabelle zu speichern und einen Fremdschlüsselverweis auf das BLOB in Ihrer Haupttabelle zu speichern. Auf diese Weise können Sie die Datei immer noch aus der Datenbank abrufen (sodass Sie keinen speziellen Code benötigen) und die Probleme mit externen DB-Abhängigkeiten (Synchronisierung von DB und Dateisystem usw.) vermeiden, aber nur diesen Overhead wenn Sie sich explizit dieser Tabelle anschließen (oder einen separaten Aufruf tätigen). 10 MB sind nicht sonderlich 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 wird, müssen Sie möglicherweise die Arbeitslast aufteilen und nur eine Art Dateideskriptor speichern. Dann können Sie einen separaten Aufruf haben, um die Datei von einem anderen Server zu laden,
quelle
Sie könnten auf einige dieser Probleme stoßen:
SELECT *
Zeile mit dem großen Blob dauert sehr lange, auch wenn Sie den Blob nicht benötigen.Natürlich erhalten Sie auch einige Vorteile:
Persönlich mache ich das nicht, da ich die Nachteile viel schwerer finde als die Vorteile. Aber wie oben erwähnt, hängt es ganz von Ihrem Anwendungsfall und so ab.
quelle
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.
quelle
Für die praktische Umsetzung können Sie Folgendes in Betracht ziehen:
Vorteile:
Nachteile:
quelle