WebWork Magazin - Webseiten erstellen lassen, Online Medien, html

Webhoster, Webhosting Provider und Domain registrieren

Home | Registrieren | Einloggen | Suchen | Aktuelles | GSL-Webservice | Suleitec Webhosting
Reparatur-Forum | Elektro forum | Ersatzteilshop Haushalt und Elektronik


Homepage und Webhosting-Forum

Scripte und Programme für PHP, MYSQL. Diskussionen zur Programmierung im Web. Fragen zu CMS, Blogsoftware, Shops, Newsletter und vielen weiteren Scripten.


Forum » PHP & MySQL » Script-Tuning » Antworten
Benutzername:
Passwort: Passwort vergessen?
Inhalt der Nachricht: Fett | Kursiv | Unterstrichen | Link | Bild | Smiley | Zitat | Zentriert | Quellcode| Kleiner Text
Optionen: Emailbenachrichtigung bei Antworten
 

Script-Tuning
von Ori
Der Code muss angepasst werden, um auch neue Einträge verarbeiten zu können, dazu ist es aber nötig, die API des $db-Objektes zu kennen.

Du musst also zuerst prüfen, ob ein Datensatz mit solch einer id bereits vorhanden ist (etwa mit SELECT COUNT(*)) und dann entscheiden, ob ein neuer Datensatz angelegt werden muss (INSERT, quasi der alte Ansatz), oder ob eine UPDATE-Anweisung ausreicht.
von raiserle
Hab jetzt nicht alles durchgelesen, nur den letzten Beitrag.

Aber mein Vorschlag...
Öffne die Datei, und lies einen Datensatz ein, ab letzter Position vom Filepointer. Wenn noch ein Datensatz vorhanden ist, weitermachen .. nächsten Datensatz holen und letze Position vom Dateiziger holen.
So wie ich das mitbekommen habe, willst den ja in eine DB haben.
Also schreib den Datensatz in die DB und speicher dir die Position des Filepointers.
schliesse die Datei.
Mach ein header() auf das selbige Script.
So sollte ein DS nach dem anderen in die DB wandern, ohne das du die komplette Datei in den Speicher haust.

Gruß raiserle
von corny
Die Datei selber(die größte) ist 11,39 mb groß.
offiziell stehen mir 9mb RAM zur Verfügung.
Das Script wird aber erst bei Überschreiten der 10 MB abgebrochen.

Ja, es gibt auch Einträge in der Datei, die komplett in die DB übernommen werden müssen, also nicht nur geupdated werden müssen.

ist es möglich, dass man die Datei splittet und bei jedem Scriptaufruf nur eine der Dateien eingelesen werden? Ist es dann möglich, dass sich das Script nach Durchlauf einfach erneut aufruft?
von Ori
chip schrieb am 08.08.2007 11:21
Ori schrieb am 08.08.2007 00:48
file_get_contents lädt die (nach corny überdimensional große) Datei in den RAM, was wohl die Providervorgabe sprengen dürfte, insofern ist zeilenweises Abarbeiten vermutlich nötig (und bei einer riesigen Datei wohl auch schneller als das Zerlegen eines gewaltigen Strings).


Ist es hier nicht das selbe? Dann wird eben Zeile für Zeile eingelesen und belastet trotzdem den RAM.

Via file_get_contents wird die gesamte Datei auf einmal in den RAM gelesen. Wenn die Datei zeilenweise gelesen wird, ist nicht alles gleichzeitig im RAM, sondern nur die gelesene Zeile (und ein bisschen für die Verwaltung des Dateizugriffs, das ist aber vernachlässigbar).

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
9: 
10: 
11:
$filearray = fopen ($file, 'r');

while (!feof($filearray))
{
    $line = fgets($filearray);
    $arr = explode(',', $line);
    $sql = 'UPDATE ' . VILLAGE_TABLE . ' SET points = \'' . $arr[5] . '\', rank = \'' . $arr[6] . '\' WHERE id = \'' . $arr[0] . '\' LIMIT 1';
    $db->sql_query($sql);
}

fclose ($filearray);

Ein paar Kommentare dazu: Ich vertraue list() nicht, weil das wohl intern in einfache Variablenzuweisungen umgemünzt wird, wir aber nur drei der sieben Werte wissen wollen. Abspeichern der Variablen für einmalige Verwendung bringt auch keinen Geschwindigkeitszuwachs.

Stehen in der Textdatei eigentlich auch neue Einträge, die vorher nicht in der Datenbank standen? Und: Wie groß ist die Textdatei eigentlich?
von corny
chip schrieb am 08.08.2007 11:21

$id, $name,$x, $y und $player würde sich dabei, wenn alles richtig läuft nie verändern, nur $points und $rank.


Warum wird es dann in die Textdatei geschrieben und ausgelesen?


Zia, da kann ich leider gar nichts dran ändern.
Der Inhalt der Textdatei wird mir so geliefert wie er ist.
Mein Job ist es nur diese Textdatei möglichst, RAM, schonend in die DB zu befördern.
von chip
Ori schrieb am 08.08.2007 00:48
file_get_contents lädt die (nach corny überdimensional große) Datei in den RAM, was wohl die Providervorgabe sprengen dürfte, insofern ist zeilenweises Abarbeiten vermutlich nötig (und bei einer riesigen Datei wohl auch schneller als das Zerlegen eines gewaltigen Strings).


Ist es hier nicht das selbe? Dann wird eben Zeile für Zeile eingelesen und belastet trotzdem den RAM.


$id, $name,$x, $y und $player würde sich dabei, wenn alles richtig läuft nie verändern, nur $points und $rank.


Warum wird es dann in die Textdatei geschrieben und ausgelesen?
von progrookie
1:
$arContent = file($this->Path);

...was würde dagegen sprechen beispeilsweise so die Datei durch zulesen?
Datei wird ín ein Array hinein geladen, welches man auch Zeilenweise durchgehen kann.
von Ori
Für ein paar Erdnüsse kannst Du noch "-Strings in '-Strings umwandeln, solange Du das Einsetzen von Variablen nicht brauchst.

file_get_contents lädt die (nach corny überdimensional große) Datei in den RAM, was wohl die Providervorgabe sprengen dürfte, insofern ist zeilenweises Abarbeiten vermutlich nötig (und bei einer riesigen Datei wohl auch schneller als das Zerlegen eines gewaltigen Strings).

Wenn die id ausreicht, um einen Spieler zu identifizieren (was irgendwie Sinn macht), würde es reichen, wenn Du nur diese abspeicherst, um beim Einlesen Zeit zu gewinnen (die anderen Daten stehen ja in der Datenbank).
von chip
file_get_contents() und explode("\n", $bla) wären hier die bessere Wahl, anstatt immer Zeile für Zeile aus der Datei zu holen.
Da, wie Du sagst $id immer gleich bleibt, mach es doch so:

1:
"UPDATE " . VILLAGE_TABLE . " SET points = '".$points."', rank = '".$rank."' WHERE id = '".$id."' LIMIT 1"


// Edit: LIMIT hinzugefügt
von corny
ja, das weiß ich ja, die Einträge sind ja auch alle Nummeriert.
Die Frage ist nur, ob es besser wäre, mit diesem Vergleich ...

Anbei das Script, falls dir sonst noch was auffällt, was man verbessern könnte...
1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17:
$file = $phpbb_root_path . $import_path . "village.txt";
$sql = "TRUNCATE TABLE `".VILLAGE_TABLE;
mysql_query($sql);

$filearray = fopen ($file, "r");
while (!feof($filearray)) {
    $line = fgets($filearray);
	list($id, $name,$x, $y, $player, $points, $rank) = explode(',', $line);
	$name = datadecode($name);
	$name = addslashes($name);
	$sql = "INSERT INTO " . VILLAGE_TABLE . " SET id='$id', name='$name', x='$x', y='$y', player='$player', points='$points', rank='$rank'";
	$db->sql_query($sql);
}

fclose ($filearray);

$id, $name,$x, $y und $player würde sich dabei, wenn alles richtig läuft nie verändern, nur $points und $rank.

Gibt es eventuell eine Möglichkeit die Ram, die ein Script belegt mittendrin zurück zusetzten, oder so?
von chip
Bei UPDATE ist wie bei allen anderen Abfragen auch, eine WHERE-Klausel möglich, die Dir entsprechende Vergleichsmöglichkeiten bietet.
von corny
Naja, bei UPDATE müsste ich ja erst abfragen, ob sich, und wenn ja was sich verändert hat.
Jetzt ist die Frage was günstiger ist.
Ist UPDATE auch besser, wenn ich vorher vergleichen muss?
von chip
corny schrieb am 04.08.2007 20:05
Das es bei UPDATE immer besser ist erst zu löschen und neu zu erstellen wusste ich nicht.


Ganz im Gegenteil. Das ist es nicht, was ich gesagt habe! UPDATE ändert Werte bei bereits vorhandenen Zeilen. Alles zu löschen und neu zu erstellen ist total sinnlos.
REPLACE fügt neue Zeilen ein, wobei bereits bestehende mit den selben Werten ignoriert werden (also nicht überschrieben werden).
von corny
Aso, ok...
Das es bei UPDATE immer besser ist erst zu löschen und neu zu erstellen wusste ich nicht.
Und wie ist es bei REPLACE?
Ist das sinnvoll?

Sonst noch Tuning-Ideen?

Soll ich das Script mal posten?
von chip
Ich verstehe Dein Problem noch nicht ganz. Denn wenn Du Dateien einliest kommt es an dieser Stelle (also beim Einlesen) ja zu dem besagten Fehler und nicht beim Update der MySQL-Tabelle.
Meinst Du am Ende vielleicht auch REPLACE anstatt UPDATE? Denn ein UPDATE ist immer sinnvoller als alles zu löschen und neu zu schreiben.
von corny
Hallo erstmal.

Ich habe ein Problem mit einem Sript. Wenn ich dieses Script von nem Cronjob ausführen lasse (ist eigentlich egal ob von nem Cronjob oder nicht), dann belegt es zuviel Ram. Mein Hoster hat das leider begrenzt, so dass das Script nach einer bestimmten Zeit automatisch abgebrochen wird und einen 500er liefert.

Nun bleibt mir nichts anderes übrig als das Script zu tunen.
Im Ur-Zustand war es ein Script, dass 3 Dateien öffnet und diese in die Datenbank einpflegt. Nun habe ich es schon so verändert, dass es 3 Scripte mit jeweils einer Datei sein. Das klappt leider nicht; da eine der Dateien unverhältnismäßig groß ist.

Jetzt muss ich also am Script selber etwas ändern. Nun also zu meiner Frage:
Ist es Arbeitsspeicher-technisch sinnvoller erst die Tabelle in der Datenbank zu leeren und dann zeilenweise wieder zu füllen (weil nur die neuen Daten sind relevant), oder ist es besser das ganze per "UPDATE" zu machen?
Hättet ihr sonst noch Ideen, wie man das Problem beheben/umgehen kann?

Gruß, Corny


---
www.webworxis.de

Nach oben