Dateibasiertes Speichern großer Datenmengen
Julian von Mendel
- php
Hi!
Ich möchte ein Schülerverwaltung mit ca. 2500 Schülern und jeweils ca. 70 Informationen aufbauen (also z. B. Geburtsdatum, Wohnort usw.). Es steht keine Datenbank zur Verfügung, es soll alles dateibasiert laufen. Wie speichere ich diese Daten mit möglichst wenig Aufwand und sehr hoher Performance?
Vielen Dank
Julian
hi,
Ich möchte ein Schülerverwaltung mit ca. 2500 Schülern und jeweils ca. 70 Informationen aufbauen (also z. B. Geburtsdatum, Wohnort usw.). Es steht keine Datenbank zur Verfügung, es soll alles dateibasiert laufen. Wie speichere ich diese Daten mit möglichst wenig Aufwand und sehr hoher Performance?
in dem du an dem punkt
Es steht keine Datenbank zur Verfügung
abhilfe schaffst.
gruß,
wahsaga
Hello,
schau Dir das noch nicht ganz ferige Beispiel der "Adressverwaltung" unter http://selfhtml.bitworks.de an. Da kannst Du auch 10.000 Schüler ohne DBMS verwalten, wenn Du Lust hast. Nur das Problem der Indexierung (damit die absoluten Satznummern gegen logische getauscht werden können) musst Du noch selber lösen.
Harzliche Grüße aus http://www.annerschbarrich.de
Tom
Hi!
schau Dir das noch nicht ganz ferige Beispiel der "Adressverwaltung" unter http://selfhtml.bitworks.de an. Da kannst Du auch 10.000 Schüler ohne DBMS verwalten, wenn Du Lust hast.
Danke, dank dir hab ich es in 30min geschafft die Performance meines Programms extrem zu steigern (ganz ehrlich...hab davor eine ziemlich schlechte Lösung gehabt, die schon bei 300 Schülern Probleme gemacht hat).
Nur das Problem der Indexierung (damit die absoluten Satznummern gegen logische getauscht werden können) musst Du noch selber lösen.
Das verstehe ich nicht.
Schöne Grüße
Julian
Hello,
Danke, dank dir hab ich es in 30min geschafft die Performance meines Programms extrem zu steigern (ganz ehrlich...hab davor eine ziemlich schlechte Lösung gehabt, die schon bei 300 Schülern Probleme gemacht hat).
Nur das Problem der Indexierung (damit die absoluten Satznummern gegen logische getauscht werden können) musst Du noch selber lösen.
Das verstehe ich nicht.
Eine Datenbank hat auf den Zugriffswegen unterschiedliche Schichten. In meinem Beispiel habe ich nur die Ankoppeltung an die Hardwareschicht betrieben. Dort wird mit der physischen Datensatznummer gearbeitet, also die Nummer aus der Position in der Datei ermittelt. das Funktionierit nur bei Einzelplatzanwendungen zuverlässig. Bei konurrierendem Betrieb muss man die physische Nummer geben eine logische austauschen. Die ID ist dann nicht mehr berechenbar, sondern sie gehört zu den Metadaten des Datensatzes. Der Datenbank-User mus oder sollte gar keinen direkten Zugriff auf dieses Datenfeld des Satzes haben. Wenn der Satz nun verschoben wird, dann nimmt er die Nummer mit. Die Nummer ist dann also keine Adresse mehr, sondern ein Name.
Nun muss man aber trotzdem noch wieder die Adresse des Datensatzes ermitteln können, damit man ihn holen lassen kann. Das macht man eben über eine Indexierung. Man schreibt eine geordnete Liste, in der Die Adresse des Satzes dem Namen gegenübergestellt wird. Diese Liste ist im einfachsten Fall durch binäre Suche durchsuchbar. Da kann man Einen aus Tausend dann eben mit maximal 10 Zugriffen ausfindig machen, oder eben Einen aus 4096 mit 12 Zugriffen.
Wenn Du nun also die nächsten Wrapper für die bereits vorhandenen Funktionen schreibst (Select Record, Update Record, Delete Record, Insert Record und Show Empty Form) dann benötigst Du eine Funktion für Get_Next_ID() (also quasi einen Counter) und eine für InsertIndex, DeleteIndex, FindIndex, UpdateIndex... Und sicherheitshalber eine ReIndex()-Funktion
Die get_next_id() hänge ich hier dran...
<?php ### get_autokey.php ###
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
function softlock( $lockfile_name, ## Qualifizierter Dateiname $mode, ## Öffnungs- und Sperranforderung &$lastwrite, ## Letztes Aktualisierungsdatum &$error_no ## Duchgeschleifter Fehler ) { $php_errormsg =''; ## ist nicht angelegt, solange ## kein Fehler auftrat $lastwrite = false; ## kein Modifikationsdatum vorhanden
if ($error_no > 0) return false; ## Bei Vorfehler abbrechen
## Lockmode feststellen $lockmode = strtoupper($mode);
if ($mode == 'W') { $openmode = 'rb+'; $lockmode = LOCK_EX; } elseif ($mode == 'C') { $openmode = 'xb+'; $error_no = 8; ## Datei wurde angelegt $lockmode = LOCK_EX; } elseif($mode == 'R') { $openmode = 'rb'; $lockmode = LOCK_SH; } else { $error_no = 100; ## falsche Funktionsnutzung return false; }
## Dateihandle beschaffen
for ($x=0;$x<5;$x++) ## Schleife 5 mal durchlaufen { clearstatcache(); $php_errormsg = '';
if($lh = @fopen($lockfile_name,$openmode)) { $error_no = 0; break; ## oder bei Erfolg abbrechen } else { $errormsg = strtolower($php_errormsg);
if(strpos($errormsg,'invalid argument')!==false) { $error_no = 101; ## hier könnte man auch überlegen $openmode = 'a+'; ## es doch mit rb+ zu versuchen
if ($fh1 = fopen($lockfile_name,$openmode)) { $openmode = 'rb+'; ## es doch mit rb+ zu versuchen fclose($fh1); ## Hilfshandle wieder abgeben $error_no = 8; } else return false; } elseif(strpos($errormsg,'illegal operation argument')!==false) { $error_no = 101; $openmode = 'a+'; ## Datei hilfsweise mit a+ anlegen
if ($fh1 = fopen($lockfile_name,$openmode)) { $openmode = 'rb+'; ## es doch mit rb+ zu versuchen fclose($fh1); ## Hilfshandle wieder abgeben $error_no = 8; } else return false; } elseif(strpos($errormsg,'no such file or directory')!==false) { $error_no = 2; return false; } elseif(strpos($errormsg,'permission denied')!==false and $error_no == 8) { return false; ## damit Fehler 8 überhaupt nach draußen kommt } elseif(strpos($errormsg,'permission denied')!==false) { $error_no = 5; return false; } elseif(strpos($errormsg,'file exists')!==false) { $openmode = 'rb+'; } } ## zur Zeit sind fopen() und dio_open() noch nicht aufeinander abgestimmt ## Eine Verzögerung beim Öffen ist daher noch nicht sinnvoll
#usleep(8000); ## 8ms warten bis zum nächsten } ## Öffnungsversuch
if (!$lh) { $error_no = 5; ## konnte Datei nicht öffnen return false; ## bei Misserfolg Funktionsende }
# Lockversuch for ($x=0;$x<5;$x++) { if (@flock($lh,$lockmode + LOCK_NB)) { $lastwrite = filemtime($lockfile_name); ## letzes Modifikationsdatum return $lh; } usleep(8000); ## 8ms warten bis zum nächsten Versuch }
$error_no = 6; ## konnte Datei nicht sperren fclose($lh); return false; } #------------------------------------------------------------------------------
#------------------------------------------------------------------------------
function get_autokey($keyfilename, ## Name der Schlüsseldatei, $indexname, ## Name der Datei, für deren DS der Schlüssel &$error_no) ## Fehlernummer {
if (strlen($indexname)==0 or is_numeric($indexname)) { $error_no = 100; ## Function Misuse return false; }
$indexname = strtolower($indexname);
$fh = softlock($keyfilename,'C',$date,$error_no); ## Schlüsseldatei öffen if (!$fh) return false;
$filesize = filesize($keyfilename);
if ($filesize > 0) {
$keystream = fread($fh, $filesize); if ($keystream === false) { $error_no = 4; ## read Error fclose($fh); return false; }
$_keyarr = unserialize($keystream); if ($_keyarr === false or !is_array($_keyarr)) { $error_no = 34; ## Decodierungsfehler fclose($fh); return false; } } else $_keyarr = array();
$_keyarr[$indexname]++;
$keystream = serialize($_keyarr); $streamlen = strlen($keystream);
fseek($fh,0,SEEK_SET); $write_ok = fwrite($fh,$keystream);
if ($write_ok != $streamlen) { $error_no = 33; ## Schreibfehler fclose($fh); return false; }
ftruncate($fh,$streamlen); fclose($fh);
return $_keyarr[$indexname]; }
#------------------------------------------------------------------ $date=0; $error = 0; $lockfile ='index.idx'; $filename ='ADRESSEN';
echo "Nächster Schlüssel für <b>$filename</b> lautet ".get_autokey($lockfile,$filename,$error).'<br />';
echo "Fehler lautet $error <br />";
$lockfile ='index.idx'; $filename ='Rosen';
echo "Nächster Schlüssel für <b>$filename</b> lautet ".get_autokey($lockfile,$filename,$error).'<br />';
echo "Fehler lautet $error <br />";
$lockfile ='index.idx'; $filename ='Aufgaben';
echo "Nächster Schlüssel für <b>$filename</b> lautet ".get_autokey($lockfile,$filename,$error).'<br />';
echo "Fehler lautet $error <br />";
?>
Harzliche Grüße aus http://www.annerschbarrich.de
Tom
Hallo Julian,
Ich möchte ein Schülerverwaltung mit ca. 2500 Schülern und
jeweils ca. 70 Informationen aufbauen (also z. B. Geburtsdatum,
Wohnort usw.). Es steht keine Datenbank zur Verfügung, es soll
alles dateibasiert laufen. Wie speichere ich diese Daten mit
möglichst wenig Aufwand und sehr hoher Performance?
Hört sich ganz nach einem Fall für B-Baum-Algorithmen an:
http://de.wikipedia.org/wiki/B-Baum
Grüße,
CK
Hallo,
danke an euch für die Hilfe! Jetzt geht's einwandfrei, und dank Toms langen Text und dem Link von Christian hab ich auch genug zum Lesen und Verstehen, fürs Wochenende zumindest :)
Schöne Grüße
Julian