Hilfe zu langsame Datenbank!

MatMagic

Erfahrenes Mitglied
Hallo Community,
nach langer Zeit habe ich (endlich) mal wieder eine Frage an euch. :-)
Ich habe in einer Tabelle die Felder:
a, b, feld, herzog, punkte
Die Positionen "a" und "b" sind Standorte auf einer Karte von 850x850 also gibt es 722500 Einträge. Aktualisierte Einträge sind immer ca. 40000 - 50000.
Ich möchte nun in den Feldern: "feld, herzog, punkte" eine aktualisierung vornehmen die den enstprechenden "a" und "b" Positionen entsprechen.
Sämtliche geänderten Informationen (a, b, feld, herzog, punkte) stehen in einer Textdatei zur Verfügung. Diese Textdatei werte ich aus und trage die Änderungen in die Tabelle ein. Aber das dauert tierisch lange.....habt ih eine Idee wie ich das schneller hinbekomme?

1.Code
Code:
<?php
include '../logindb.php';
$connectionid  = mysql_connect($l1,$l2,$l3);
	if (!mysql_select_db ($l4, $connectionid))
	{
 	die ("Keine Verbindung zur Datenbank");
	}
     $datei = "quelle.txt";  
     $lines = file($datei);
     foreach ($lines as $line) 
     { 
     $zeile = explode('%|', trim($line));
	 $a = $zeile[0];
                 $b = $zeile[1];
	 $feld = $zeile[2];
	 $herzog = $zeile[3];
	 $punkte = $zeile[4];
     // Einträge Update
     $sql = "UPDATE `force_entry` SET ".
       "`feld` = '$feld, ".
       "`herzog` = '$herzog, ".
       "`punkte` = '$punkte".
       "WHERE `a` = '$a' and `b` = '$b'";
     // SQL Befehl ausführen
     mysql_query ($sql);
     }
?>

Das war seeeeehr langsam jeder Eintrag hat ca. 6 Sekunden gedauert was bei 40.000 Änderungen ca. 67 Stunden entsprechen würde. Deswegen habe ich in die Tabelle das Feld "ab" hinzugefuegt in dem nun die Werte "a" und "b" so drinstehen "a_b" und somit das updaten von 2 Bedingungen auf 1 Bedingung reduziert.

2.Code
Code:
<?php
include '../logindb.php';
$connectionid  = mysql_connect($l1,$l2,$l3);
	if (!mysql_select_db ($l4, $connectionid))
	{
 	die ("Keine Verbindung zur Datenbank");
	}
     $datei = "quelle.txt";  
     $lines = file($datei);
     foreach ($lines as $line) 
     { 
     $zeile = explode('%|', trim($line));
	 $ab = $zeile[0]."_".$zeile[1];
	 $feld = $zeile[2];
	 $herzog= $zeile[3];
	 $punkte = $zeile[4];
     // Einträge Update
     $sql = "UPDATE `force_entry` SET ".
       "`feld` = '$feld, ".
       "`herzog` = '$herzog, ".
       "`punkte` = '$punkte".
       "WHERE `ab` = '$ab'";
     // SQL Befehl ausführen
     mysql_query ($sql);
     }
?>

Das hat leider nicht viel gebracht....ein Eintrag dauert nun ca. 4 .5 Sekunden was bei 40000 Änderungen immer noch satte 50 Stunden sind. Ich gehe mal davon aus das ich etwas grundlegendes falsch mache. Leider weiss ich nicht was. Google oder die Forensuche haben mir bisher leider keinen Erfolg beschert.

An der Auswertung der Textdatei kann es eigentlich nicht liegen, da die Auswertung (ohne die DB Eintragung) - nur Darstellung auf dem Bildschirm für alle 722500 Einträge insgesamt nur ca. 60 Sekunden dauert.

Habt ihr eine Idee warum das so lange dauert? Geht es überhaupt schneller?

Gruß
Mat
 
Zuletzt bearbeitet:
Hallo!

Der Inhalt der Textdatei wird ja auch "nur" ausgewählt und ausgegeben.
Die Datenbank hingegen muss erstmal den entsprechenden Datensatz suchen und dann aktuallisieren..... dass alleine das suchen länger dauert, sollte wohl einleuchtend sein. ;)

Aber warum aktuallisierst Du nicht jeden einzelnen Eintrag sofort, anstatt alle Einträge erstmal in einer Textdatei zu "sammeln"?!
Ich kann mir auch nicht wirklich etwas über das Projekt vorstellen..... ausser dass ein Standort einem Pixel entspricht.

Gruss Dr Dau
 
Hallo Dr.Dau!
Der Inhalt der Textdatei wird ja auch "nur" ausgewählt und ausgegeben.
Die Datenbank hingegen muss erstmal den entsprechenden Datensatz suchen und dann aktuallisieren..... dass alleine das suchen länger dauert, sollte wohl einleuchtend sein

^^Na sicher ist mir das klar :-) ich wollte nur im Vorfeld darauf hinweisen das es nicht an dem auslesen der Textdatei liegen kann - damit ich keine Antworten bekomme das es halt an der TextDatei liegen könnte.

Aber warum aktuallisierst Du nicht jeden einzelnen Eintrag sofort, anstatt alle Einträge erstmal in einer Textdatei zu "sammeln"?!
Ich kann mir auch nicht wirklich etwas über das Projekt vorstellen..... ausser dass ein Standort einem Pixel entspricht.

Weil ich keinen Zugriff auf die Datenbank habe in der die Daten stehen. Ich habe nur die Text-Datei zur Verfügung in der nach 1 Woche, wenn ich sie bekomme die geänderten Datensätze drinstehen.
Zum Verständnis (aber wohl eher unwichtig): In der Tabelle sind die 722500 Einträge, also wie a=1, b =1 und a=2, b=1 und a=3, b=1 etc. - zu jeder a/b position ändern sich halt in gewissen Abständen die Namen von "feld", "herzog", "punkte" und diese müssen an den entsprechenden Positionen eingetragen werden.

Aber wenn ich es deiner Antwort richtig entnehme ist mein Code als solches schon ok - und die ganze Geschichte ist halt so langsam wenn man diesen Haufen an Änderungen "auf Einmal" eintragen will !?
 
Bei großen Dateien sollte mit der fopen()-Funktion gearbeitet werden, da diese mit einem Dateizeiger arbeitet und den Inhalt der Datei nicht komplett ausliest und in den Speicher lädt. Auch sind die Variablen $ab (beziehungsweise $a und $b), $feld, $herzog und $punkte überflüssig, da sie den Wert einer anderen Variable unverändert übernehmen. Weitere Verbesserungen lassen sich wohl nur beim Datenbankschema machen.
 
Hallo Gumbo, danke für die Antwort allerdings soll die ganze Datei ja eingelesen werden da darin nur die Änderungen stehen.
Das ich die Variablen "$a, $b, $herzog, etc." nochmal mit dem Inhalt von $zeile[0], etc. belegt habe war nur zur Fehlerfindung damit ich auf den ersten Blick weiss welchen Wert ich da übergebe.
Code ohne überflüssige Vars:
Code:
<?php
include '../logindb.php';
$connectionid  = mysql_connect($l1,$l2,$l3);
	if (!mysql_select_db ($l4, $connectionid))
	{
 	die ("Keine Verbindung zur Datenbank");
	}
     $datei = "quelle.txt";  
     $lines = file($datei);
     foreach ($lines as $line) 
     { 
     $zeile = explode('%|', trim($line));
     // Einträge Update
     $sql = "UPDATE `force_entry` SET ".
       "`feld` = '$zeile[2]', ".
       "`herzog` = '$zeile[3]', ".
       "`punkte` = '$zeile[4]'".
       "WHERE `ab` = '$zeile[0]."_".$zeile[1]'";
     // SQL Befehl ausführen
     mysql_query ($sql);
     }
?>
Datenbankschema.....mmmmhhhh?
Dauert ein Eintrag in ein Feld vom Typ "Text" länger als ein Eintrag in ein Feld vom Typ "Int"? (<< ernstgemeinte Frage)
 
Zuletzt bearbeitet:
Auch wenn der gesamte Inhalt der Datei verarbeitet werden soll, ist es bei großen Dateien doch effizienter, nur immer die aktuelle Zeile auszulesen statt den gesamten Inhalt auf einmal. Daneben ist auch das foreach-Kontrollkonstrukt gegenüber anderen Konstrukten langsamerer.
 
OK, danke - dann werde ich das mal testen. Ich dachte nur da die komplette Datei einlesen nur 60 sek. in Anspruch nimmt kann es meinen Code nicht so langsam machen wie er derzeit ist. Da die 60 sek. ja nur 1x entstehen habe ich gemeint das es am Eintragen in die DB liegen muss. Aber vielen Dank euch beiden erstmal!
Werde dann morgen mal meine Fortschritte (hoff) posten. :(
 
Wenn in der Textdatei (oder besser gleich in einem SQL-Dump) nicht nur die aktuallisierten Daten stehen würde, sondern alle..... dann könnte man die Tabelle auch jedesmal komplett leeren und die Daten neu eintragen.
Das würde die (doch recht umfangreiche) Suche ersparen.
 
Das Problem ist ja aber das ich die Daten nur so wie oben beschrieben geliefert bekomme. Also nur die Änderungen. Ich bin aber auch noch gar nicht dazu gekommen die von euch oben genannten Vorschläge auszuprobieren. Das mache ich natürlich erst noch und poste dann meine Fortschritte.

Auf jeden Fall schon mal Danke für die Lösungsvorschläge!
 
Hallo,

OK, danke - dann werde ich das mal testen. Ich dachte nur da
die komplette Datei einlesen nur 60 sek. in Anspruch nimmt kann es meinen Code nicht so langsam machen wie er derzeit ist. Da die 60 sek. ja nur 1x entstehen habe ich gemeint das es am Eintragen in die DB liegen muss.
Ich weiß jetzt nicht wie groß diese Datei ist, allerdings kann es beim kompletten Einlesen schon dazu kommen, dass mangels freier Speicherblöcke auf dem Heap auf den (langsamen) Swap zurückgegriffen wird. Wenn der SQL-Server auf derselben Maschine läuft, müsste dann natürlich auch dieser auf den Swap ausweichen, wenn er die Anfragen bearbeitet.

Ein weiterer Grund könnten fehlende oder falsch gesetzte Indizes bei der Datenbanktabelle sein. Auch die verwendeten Datentypen könnte man vielleicht optimaler wählen. Dazu müssten wir allerdings wissen, wie die Tabelle aufgebaut ist (die Ausgabe von DESCRIBE `tabelle` wäre da geeignet).

Schlussendlich könnte man dann auch noch auf „Prepared Statements“ zurückgreifen. Da weiß ich allerdings nicht, wie es mit der Unterstützung durch PHP aussieht.

Grüße,
Matthias
 
Zurück