Verwaltung großer Datenmengen (binär) in PHP/MSSQL
jives 03.09.2008 - 18:03 3121 21
quilty
Ich schau nur
|
Ich würde in diesem Fall die Datenbank maximal für das Managen der Verweise und die Verknüpfung mit den Meta-Daten verwenden. Die Daten selbst direkt am FileSystem hinterlegen. Ums "entpacken" bzw. einlesen der Daten in deine interne Datenstruktur wirst du so oder so nicht herumkommen und wenn du von 15k Einträge nur gut 100ms brauchst ist das durchaus ein vernünftiger Wert (alleine der Zugriff auf die HDD frisst hier schon viel Zeit). Hier kannst du maximal kleinere Optimierungen machen wie schon von Colo angedeutet, die beim erstmaligen Aufbereiten der Daten dann natürlich mehr Zeit beanspruchen, dafür anschließend etwas schneller sind. Ein Tipp für deine Anwendung noch - cachen, cachen und nochmal cachen.
|
COLOSSUS
AdministratorGNUltra
|
Ich hab keine Vorstellung davon, wie schwierig/umstaendlich es ist, eine PHP-Erweiterung in C zu schreiben... Wenn du dich aber darauf verlassen kannst, dass serialize() in diesem Fall ganz sicher einer bestimmten Form folgende Daten ausspuckt - dann kannst du ziemlich sicher auch einen effizienteren Deserialisierer schreiben, als PHP in by default hat (in schaetzungsweise eigentlich trivialem C).
|
jives
And the science gets done
|
Ums "entpacken" bzw. einlesen der Daten in deine interne Datenstruktur wirst du so oder so nicht herumkommen und wenn du von 15k Einträge nur gut 100ms brauchst ist das durchaus ein vernünftiger Wert (alleine der Zugriff auf die HDD frisst hier schon viel Zeit). Für ein File (das eben im Schnitt einem 10x1000-Array entspricht) ist das ok - leider gibt es oft Anwendungen, die mehrere Hundert solcher Lesevorgänge brauchen. Die Benchmarks zeigen auch, dass das Lesen des BLOBs aus der DB irgendwo bei 1-1,5ms braucht - der Rest geht fürs Deserialisieren drauf. @ COLO Ich leider auch nicht Aber ich hatte schon den selben Gedanken (siehe letzter Absatz in meinem ersten Post). Ich glaube aber, wenn es nicht allzu große Einwände gibt, werde ich mein Glück vorerst mit dem Ablegen der Daten in die DB versuchen (nach der oben vorgeschlagenen Struktur).
|
mat
AdministratorLegends never die
|
serialize() ist eine furchtbare Art und Weise ein Array zu verpacken. Es macht einen fast lesbaren String daraus inklusive unnötiger Delimiter. Abhilfe wird dir wohl nur eine PHP-Extension schaffen, die das für dich effizient umwandelt und am besten auch gleich direkt mit der Datenbank kommuniziert.
Btw, obwohl es hier schon gesagt wurde: Große Datenmengen in einem Table können sich höllisch auf die Performance auswirken. Wie man es dreht und wendet, besonders auf Linux ist das automatische Caching auf Filesystem-Ebene bei weitem schneller.
|
jives
And the science gets done
|
Vielen Dank für die vielen Inputs! Auf einige Ideen wäre ich sicher nicht gekommen, und andere Dinge waren mir einfach nicht bewusst. Nachdem der O-Ton doch eindeutig weg vom Ablegen der Daten in der DB und in Richtung Serialisieren/Packen und Ablegen im Dateisystem geht, werde ich wohl COLOs Vorschlag weiter verfolgen und mir eine Kombination aus eigener PHP-extension zum entpacken/deserialisieren und BDB zum Verwalten der Files in der von COLO vorgeschlagenen Struktur ansehen und werde berichten, sobald ich Ergebnisse hab (oder wieder Fragen auftauchen ). Edit: Eine Frage hätte ich noch. 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. Hab ich das richtig verstanden: Unter DATA/*/ liegt dann jeweils EIN dbm-File, welches als Key/Data-Paare Spalten/Daten-Einträge hat?
Bearbeitet von jives am 04.09.2008, 03:32
|
COLOSSUS
AdministratorGNUltra
|
Ich fasse einfach nochmal zusammen, wie ich versuchen wuerde, an eine Loesung fuer deinen speziellen Fall heranzugehen: Im jeweils untersten Verzeichnis eines solchen DATA/*/-Baumes liegen nicht mehr als rund tausend Files. Wenn du also mit einer 5stelligen Anzahl Arrays rechnen musst, und diese durch eine eindeutige, fortlaufende, dezimale Nummer indizieren willst (wird das Einfachste sein), dann hast du 2 Ebenen Verzeichnisse: ./{0..9}/{0..9}/, und in den jeweils untersten dann bis zu 1000 Dateien [0-9][0-9][0-9]. Jedes dieser Files, also ./0/0/000 bis ./9/9/999, enthaelt die BDB-Strukturen mit wahlfreiem Index als Key (deine Row# bietet sich natuerlich an), und der zugehoerige Value entspricht der wie ich auch immer serialisierten Row-Payload deines Arrays. Ich hab gestern vor der Heia noch ein bisschen gegoogelt, wie man PHP Extensions selbst zusammenschustern kann; hab zwar nur zwei Guides fuer PHP4 und MSVC++ gefunden, aber es schien keine Lebensaufgabe zu sein. You can do it! \o/
|
jives
And the science gets done
|
Kleines Update: Ich hab erste kleine Erfolge mit meiner eigenen Extension gefeiert. Momentan kann sie nicht viel mehr als Binärdaten in ein 2D-Array entpacken, ist dabei aber um einen Faktor 16 (direkt von der Harddisk) bzw. 30 (aus einem Binärsting im Speicher) schneller als ihr PHP-Pendant. Leider wird die dll mit fast 500k zu groß für meinen Geschmack und ich weiß noch nicht wieso, aber sonst schauts schon ganz gut aus Jetzt muss ich noch die DB-Struktur fixieren und mir überlegen, was ich alles in die Extension reinpacke. P.S.: Danke COLO für die nochmalige Erklärung, und danke auch allen anderen für die sehr hilfreichen und kompetenten Inputs!
|