jives
And the science gets done
|
AufgabenstellungIch brauche in einer PHP (5.2.6, IIS 6) Applikation eine große Menge an Daten in Form eines 2D-Arrays. Diese Daten kommen aus einzelnen Files in welchen diese Daten in binärer Form abgespeichert sind. Die Frage ist nun, wie ich die Daten in einer Datenbank (MSSQL Express 2005) abspeichern kann, so dass der Zugriff auf große Mengen (mit bis zu mehreren Millionen Einträgen im 2D-Array) dieser Daten einerseits möglichst schnell erfolgt, andererseits aber die Datenbank nicht nach kurzer Zeit an ihre Grenzen stößt. IststandMomentan speichere ich die Daten eines jeden Einzelfiles als eigene Zeile pro File in der DB, wobei ein Feld die binären Nutzdaten Base64-codiert enthält. PHP holt diese Daten ab und "entpackt" die Daten in 2D-Array-Form. ProblemBechmarks haben folgendes ergeben: Das Holen der Daten eines durchschnittlichen Files dauert 126ms, wobei 124,9ms lang entpackt wird. Da nun durchaus mehrere 100-1000 "Files" gelesen werden müssen, dauert alleine das Holen der Daten mehrere Sekunden bis Minuten, was wir dem User nicht antun wollen. LösungsansätzeEine Alternative wäre das Entpacken der Daten beim Eintragen in die DB, wobei man um die n x m -Struktur zu wahren zwei Tabellen gebraucht werden - die eine bekommt für jedes neue File n Einträge (erste Dimension) mit Verweis auf die File-id, die zweite n x m Einträge mit Verweis auf die entsprechende id in der ersten Tabelle. Das Problem hierbei ist, dass mir ganz schnell die IDs ausgehen werden fürchte ich, denn: Ein (durchschnittliches) File hat 15x1000 Einträge und ich habe meherere 100-1000 Files täglich in die DB einzupflegen. Die zweite Alternative ist das Entpacken beim Eintragen in die DB, aber speichern in einem 2D-Array, das mit serialize() bearbeitet wurde. Hier entstehen durch serialize() natürlich enorm große Datenmengen. Weiters hat diese Variante schon große Probleme mit der DB gemacht, und ich kenne die Performance von unserialize() nicht. Andere Möglichkeiten die mir einfallen sind: Auslagern der entsprechenden Operationen in ein C-Programm (schneller?) und Stored Procedures auf der DB (keine Ahnung ob die wirklich was bringen würden). Habt ihr Erfahrung mit solchen Anwendungen? Wie würdet ihr dieses Problem lösen? Ich wäre für jeden Input und jeden Tipp sehr dankbar
Bearbeitet von jives am 03.09.2008, 23:00 (Typos)
|
><))))°>
Idle ...
|
ich hab zwar schon länger nicht mehr beruflich mit IT zu tun, aber damals wurde mir beigebracht, dass man in so einem fall die daten als dateien auf der platte ablegt, und in der datenbank nur einen link dort hin einträgt. damit überlastet man die datenbak software nicht, und die grösse der dateien ist auch egal. edit: ich hoff ich hab dein problem richtig verstaden. ansonsten meinen beitrag einfach ignorieren
|
jives
And the science gets done
|
Den Gedanken hatte ich auch schon Das Problem des Konvertierens von Binär- zu "Nutz"-Daten bleibt bestehen. Auch wenn ich die Daten als "Klartext" mit serialize() oder einem eigenen Format speichere, bleibt das Problem des Umwandelns bestehen.
|
UncleFucka
-
|
die frage ist wohl eher ob das nicht die komplett falsche anwendung einer datenbank ist.. ich mein.. du speicherst in der datenbank files ab die aus zeilen und spalten bestehen.. so wie eine datenbank..
das beste wäre wohl ein gscheites schema zu machen und die files richtig in die datenbank einzutragen so das du direkt drauf selektieren kannst. so wirst du die files komplett los und hast die performance.
|
jives
And the science gets done
|
das beste wäre wohl ein gscheites schema zu machen und die files richtig in die datenbank einzutragen so das du direkt drauf selektieren kannst. so wirst du die files komplett los und hast die performance. Eine Alternative wäre das Entpacken der Daten beim Eintragen in die DB, wobei man um die n x m -Struktur zu wahren zwei Tabellen gebraucht werden - die eine bekommt für jedes neue File n Einträge (erste Dimension) mit Verweis auf die File-id, die zweite n x m Einträge mit Verweis auf die entsprechende id in der ersten Tabelle. Das Problem hierbei ist, dass mir ganz schnell die IDs ausgehen werden fürchte ich, denn: Ein (durchschnittliches) File hat 15x1000 Einträge und ich habe meherere 100-1000 Files täglich in die DB einzupflegen. Das ist das, was mir dazu eingefallen ist. Meinst du sowas? Wenn ja, was sagst du dann zu dem von mir angesprochenen Problem? Oder macht man das dann anders? Edit: Man könnte auch immer eine neue Tabelle mit einem eindeutigen, generierten Namen für jedes File anlegen und die Files einfach in Tabellenform ohne id oder ähnlichem schreiben. Ich weiß aber nicht, ob man sowas wirklich machen soll/kann? Das werden dann ja unzählige Tabellen. Dafür könne das Selektieren mehrerer Datensätze dann vielleicht mit JOINs durchgeführt werden...
Bearbeitet von jives am 03.09.2008, 19:03
|
that
ModeratorHoffnungsloser Optimist
|
Brauchst du für Operationen immer das ganze Array? Falls ja -> BLOBs oder Files außerhalb der Datenbank. Falls nein -> aufteilen.
|
jives
And the science gets done
|
In 99% der Fälle brauche ich das ganze Array bzw. mehrere komplette Spalten daraus.
In welcher Form meinst du soll ich die Daten ablegen? Aber wenn ich die Daten als BLOB 1:1 im Dateisystem ablege, muss ichs in PHP ja erst entpacken - das ist genau die Operation, die jetzt Probleme macht. Ich könnte probieren die Daten mit serialize() abzuspeichern, wobei die Operationen viel Speicher fressen und vermutlich nicht ausreichend perfomant sind.
Habe ich hier einen Denkfehler? Müsste ich nicht eigentlich die Daten auf jeden Fall in der DB verwalten, um ausreichende Performance gewährleisten zu können?
Meinst du mit aufteilen so wie von mir vorgeschlagen (eigene Tabelle pro File/zwei neue Tabellen für alle Files)?
|
that
ModeratorHoffnungsloser Optimist
|
Wenn du mehrere komplette Spalten brauchst, würde sich vermutlich anbieten, eine Zeile in der DB-Tabelle pro Spalte deiner binären Tabelle zu machen. Und du willst auf keinen Fall eine dynamische Anzahl von DB-Tabellen.
Und entpacken würde ichs möglichst gar nicht, sondern erst direkt beim Zugriff - gibts in PHP Byte-Arrays?
|
COLOSSUS
AdministratorGNUltra
|
Ich hab mir Muehe beim Lesen der Aufgabenstellung gegeben, aber mein geistiges Auge schafft es einfach noch nicht, das Szenario vor sich aufleben zu lassen Ist es so, dass du ... N Files hast, die N Arrays repraesentieren ... jedes dieser N Arrays aus x*y Elementen besteht ... du jedes dieser Arrays in eine Tabelle einer SQL-DB schreiben willst, um dort auf Rows und Cols Zugriff nehmen zu koennen oder habe ich da was falsch verstanden? (Es faellt mir mit dieser Anime-MMORPG-Gedudelmusik im Hintergrund hier grade etwas schwer, mich zu konzentrieren, sorry )
|
jives
And the science gets done
|
Wenn du mehrere komplette Spalten brauchst, würde sich vermutlich anbieten, eine Zeile in der DB-Tabelle pro Spalte deiner binären Tabelle zu machen. Wenn ich das richtig verstanden habe wäre das meine erste Idee: +-----------+
| Files |
+-----------+
| fid | ... |
+-----------+
+-----------------+
| Columns |
+-----------------+
| cid | fid | ... |
+-----------------+
+-------------+
| Data |
+-------------+
| cid | Data |
+-------------+
Wobei fid und cid eindeutige, fortlaufende ID's sind. Die Spalte Data in der Tabelle Data würde dann floats enthalten. Beispiel: Bei einem File mit 10x1000 Einträgen wird ein Eintrag mit fid 1 in "Files" angelegt, 10 Einträge mit cid 1 - 10 und fid 1 in "Columns" und 10000 Einträge OHNE fortlaufende ID und cid 1 - 10 in "Data". Mit SELECT * FROM Data WHERE cid > 0 AND cid < 11
könnte ich dann den gesamten Inhalt des Files mit der fid 1 auslesen. Das halte ich für eine relativ gute Lösung - was meinst du dazu? Aus Neugier noch eine Frage: Was ist an einer Lösung mit dynamisch generierten Tabellen verkehrt/schlimm? Intuitiv wollte ich das eh nicht, aber richtigen Grund habe ich keinen finden können. Ich hab mir Muehe beim Lesen der Aufgabenstellung gegeben, aber mein geistiges Auge schafft es einfach noch nicht, das Szenario vor sich aufleben zu lassen
Ist es so, dass du ... N Files hast, die N Arrays repraesentieren ... jedes dieser N Arrays aus x*y Elementen besteht ... du jedes dieser Arrays in eine Tabelle einer SQL-DB schreiben willst, um dort auf Rows und Cols Zugriff nehmen zu koennen
oder habe ich da was falsch verstanden? (Es faellt mir mit dieser Anime-MMORPG-Gedudelmusik im Hintergrund hier grade etwas schwer, mich zu konzentrieren, sorry ) Exakt das will ich Problem dabei ist eben, dass das Umwandeln der binären Repräsentation der Arrays nicht ausreichend performt. Meine obige Lösung war schon früh angedacht, aber dank eines Rechen- und eines Denkfehlers habe ich mir eingebildet in der "Data" Tabelle eindeutige ids zu brauchen, die auch noch schnell zur Neige gegangen wären. Aber bei 2^64 Möglichkeiten sollte das doch eine Zeit lang gehen
|
COLOSSUS
AdministratorGNUltra
|
Wenn dich in diesen Arrays immer nur bestimmte Zeilen interessieren, dann waere es vielleicht performanter, diese alle in eine Verzeichnisstruktur zu speichern (es ist generell besser fuer die Performance, nicht ein Directory mit tausenden Files vollzumuellen; ziemlich unabhaengig vom FS. Deshalb solltest du deinen Index, ueber den die einzelnen Files/Arrays adressiert werden, auf Verzeichnis- und Dateinamen aufteilen: DATA/1/7/901.bin statt DATA/17901.bin zum Beispiel), und die einzelnen Files jeweils von einer BDB (Berkeley Database) verwalten lassen. Da kannst du deinen wie auch immer serialisierten Inhalt der Rows (Google Protocol Buffers waeren hier vielleicht eine nuetzliche Sache, wenn PHPs internes serialize() suckt (was ich mal annehme)?) mit deren Row-Nummer als Index ablegen, und wohl auch entsprechend schnell rausholen.
|
that
ModeratorHoffnungsloser Optimist
|
+-------------+
| Data |
+-------------+
| cid | Data |
+-------------+
D.h. die Reihenfolge deiner Daten ist irrelevant? Weil die bekommst du so nicht mehr heraus.
|
jives
And the science gets done
|
Vielen Dank an COLO und that für die (wie immer ) hervorragenden Inputs @ COLO An sowas hab ich noch gar nicht gedacht (wär auch nie darauf gekommen). Das scheint eine sehr gute Methode zu sein, die wir uns sicher genau anschauen werden. @ that Doch die Reihenfolge ist enorm wichtig. Ich hätte fast vergessen, dass es nicht reicht die Daten in der richtigen Reihenfolge in die DB zu schreiben. Stimmt ja leider nicht, weil ich die ja irgendwie zurück bekommen kann beim Lesen. Ich führe dann wohl am besten eine 64bit-ID mit, nach der ich sortieren kann. Die sollte auch für die nächsten tausend Jahre funktionieren
|
that
ModeratorHoffnungsloser Optimist
|
Dumme Frage #1: Warum gerade PHP? In einer Microsoft-Umgebung würde sich doch .Net anbieten. Dumme Frage #2: Was macht das PHP-Programm mit den Daten? Davon hängt die passende Datenbankstruktur ab. Dumme Frage #3: Warum überhaupt Datenbank? Werden die Daten nach dem Laden irgendwann nochmal verändert?
|
jives
And the science gets done
|
#1: Um ehrlich zu sein: Weil das Know-How für .NET nicht vorhanden ist #2: Graphische Darstellung in Form von Diagrammen, die nach Benutzereingaben generiert werden. #3: Weil zu den Daten ein Haufen Metadaten gehört, die alle mit einander verknüpft sind. Nachdem die Daten in der DB sind, werden unter Umständen die zugehörigen Metadaten verändert.
|