While Schleife - Zu bestimmter Stelle springen

Mitglied: ottscho

ottscho (Level 2) - Jetzt verbinden

08.03.2013 um 08:09 Uhr, 3672 Aufrufe, 15 Kommentare, 1 Danke

Moin,

ich habe ein Import, mit welcher ich 100t Datensätze aus einer CSV in eine DB importiere.
Das Ganze läuft über ein Script, welches sich wegen Servertimeout immer wieder selbst aufruft.
Es gibt ein Step Wert und ein Offset Wert.

Step=500
Offset0

D.h. Gestartet wird mit dem Datensatz 0 und es werden 500 abgearbeitet. Dann wird das Script erneut aufgerufen mit dem Step=500 und dem Offset= 500.
Jetzt werden die ersten 500 Datensätze übersprungen und dann geht es ab 500 weiter mit dem Import. usw.






Jetzt meine Frage. Je länge, das Script läuft, um so langsamer wird es bei den letzte Datensätzen. Da ja z.B bei dem Offset 50000, davor in der Schleife erst mal 49999 übersprungen werden, bis dann ab 50000 die nächsten 500 importiert werden.

Es muss doch möglich sein, direkt den Einstiegspunkt mitzugeben. So dass nicht erst die bereits importierten Datensätze übersprungen werden müssen.

ich hoffe ihr versteht wie ich das meine ;)

Besten Dank

Gruß ottscho
Mitglied: flow.ryan
08.03.2013 um 08:50 Uhr
Zitat von @ottscho:
Moin

Hallo


ich habe ein Import, mit welcher ich 100t Datensätze aus einer CSV in eine DB importiere.
Das Ganze läuft über ein Script, welches sich wegen Servertimeout immer wieder selbst aufruft.
Es gibt ein Step Wert und ein Offset Wert.

Step=500
Offset0

D.h. Gestartet wird mit dem Datensatz 0 und es werden 500 abgearbeitet. Dann wird das Script erneut aufgerufen mit dem Step=500
und dem Offset= 500.
Jetzt werden die ersten 500 Datensätze übersprungen und dann geht es ab 500 weiter mit dem Import. usw.

Idee ist okay.. aber:


Jetzt meine Frage. Je länge, das Script läuft, um so langsamer wird es bei den letzte Datensätzen. Da ja z.B bei
dem Offset 50000, davor in der Schleife erst mal 49999 übersprungen werden, bis dann ab 50000 die nächsten 500
importiert werden.


Und hier hast du den Grund dafür. Das Teil muss ja so jedes Mal alle vorherigen Datensätze "überspringen".


Du hättest jetzt folgende Möglichkeiten, die Ausführungszeit hoch zu setzen - was ich nicht besonders schön finde.
Leider weiß ich nicht, wie du genau den Import löst.
Läuft das per MySQL und INSERT's?

Wenn ja, dann schau dir mal folgende Funktion an:
http://dev.mysql.com/doc/refman/5.1/de/load-data.html
Bitte warten ..
Mitglied: ottscho
08.03.2013 um 09:12 Uhr
danke für dein input.

Es läuft über eine API der Shopschnittstelle.
Hinter der API stehen dann MYSQL INSERTS und UPDATES.

Die API selbst kann ich nicht anpassen.
Bitte warten ..
Mitglied: flow.ryan
08.03.2013 um 09:16 Uhr
Ah okay,

vielleicht wäre noch folgendes möglich:

Du durchläufst die 5000 INSERTs und nimmst dann die ersten 5000 Einträge aus der Datei raus.
Somit wird die Datei kleiner und du kannst dir die Durchläufe der Schleife sparen.
Bitte warten ..
Mitglied: nxclass
08.03.2013 um 09:17 Uhr
Das Ganze läuft über ein Script, welches sich wegen Servertimeout immer wieder selbst aufruft
... umgehen kann man dies in dem man das php Skript direkt auf der Konsole aufruft. Oder man macht den Shell Aufruf aus deinem Web-PHP Skript
so bekommst du die Prozess ID zurück und hast die Ausgaben in Log Dateien.
Bitte warten ..
Mitglied: 64748
64748 (Level 2)
08.03.2013, aktualisiert um 10:05 Uhr
Guten Morgen,
Zitat von @ottscho:
...
Jetzt meine Frage. Je länge, das Script läuft, um so langsamer wird es bei den letzte Datensätzen. Da ja z.B bei
dem Offset 50000, davor in der Schleife erst mal 49999 übersprungen werden, bis dann ab 50000 die nächsten 500
importiert werden.

Es muss doch möglich sein, direkt den Einstiegspunkt mitzugeben. So dass nicht erst die bereits importierten Datensätze
ich hab von PHP keine Ahnung, soviel vorweg ;-) face-wink

ich würde, wenn ich sowas mit Perl mache, einen etwas anderen Ansatz wählen (oder zumindest ausprobieren).
Eine Schleife 50000 mal zu durchlaufen kostet Zeit. Stattdessen würde ich die letzte verarbeitet Zeile (oder eine Teilzeichenkette daraus) in einer Datei speichern. Wenn das Programm wieder startet, dann öffnet es die csv-Datei und liest die Zeichenkette ein. Wenn nun in der geöffneten Datei nach der Zeichenkette gesucht wird (PHP wird ja eine Variante von grep haben), dann geht das höchstwahrscheinlich erheblich schneller als Schleifendurchlauf. Die Geschwindigkeit hängt auch davon ab, welchen Teilstring man verwendet (sollte so verschieden als möglich von anderen Strings sein).


Gerade ausprobiert mit Perl, es bringt nichts.

Markus
Bitte warten ..
Mitglied: Lochkartenstanzer
08.03.2013 um 09:57 Uhr
Moin,

was ich mich frage ist, warum man eine Interpretersprache dafür nimmt? Ich würde da einfach ein C-Binary daraus machen (notfall smit PHC & gcc) und dann das aufrufen.

Was spricht eigentlich dagegen die Eingangsdatei einfach in Häppchen zu je 500 Datensätzen (als Einzeldateien) aufzuteilen und dann den Import auf jeweils diese Häppchen loszulassen?

lks
Bitte warten ..
Mitglied: ottscho
08.03.2013 um 10:05 Uhr
moin,


>was ich mich frage ist, warum man eine Interpretersprache dafür nimmt? Ich würde da einfach ein C-Binary daraus >machen (notfall smit PHC & gcc) und dann das aufrufen.

Naja, die Shopschnittstelle für den Import ist eine API in PHP.

>Was spricht eigentlich dagegen die Eingangsdatei einfach in Häppchen zu je 500 Datensätzen (als Einzeldateien) >aufzuteilen und dann den Import auf jeweils diese Häppchen loszulassen?

nichts. so läuft im moment der erste ansatz. wir machen 10t csv Splittdateien. Sprich die Eingangsdatei mit den 120t Artikel wird in 12 Einzeldateien gesplittet.

Dies sollte schon sehr viel Zeit sparen.
Bitte warten ..
Mitglied: Lochkartenstanzer
08.03.2013 um 10:47 Uhr
Zitat von @ottscho:
moin,


>was ich mich frage ist, warum man eine Interpretersprache dafür nimmt? Ich würde da einfach ein C-Binary daraus
>machen (notfall smit PHC & gcc) und dann das aufrufen.

Naja, die Shopschnittstelle für den Import ist eine API in PHP.

Da gibt es trotzdem Möglichkeiten, wie gesagt zur Not mal PCH ausprobieren.


>Was spricht eigentlich dagegen die Eingangsdatei einfach in Häppchen zu je 500 Datensätzen (als Einzeldateien)
>aufzuteilen und dann den Import auf jeweils diese Häppchen loszulassen?

nichts. so läuft im moment der erste ansatz. wir machen 10t csv Splittdateien. Sprich die Eingangsdatei mit den 120t Artikel
wird in 12 Einzeldateien gesplittet.

Dies sollte schon sehr viel Zeit sparen.

Sind die CSV-Datensätze "einzeilig", d.h. pro Datensatz eine zeile oder sind da zeilenumbrüche drin? Wenn sie einzeilig sind, könnte man durch ein einfaches


eine temporäre Datei erzeugen, die genau die gerade zu bearbeitenden Sätze enthält und schnell genug sein sollte

lks
Bitte warten ..
Mitglied: 64748
64748 (Level 2)
08.03.2013, aktualisiert um 10:57 Uhr
Zitat von @Lochkartenstanzer:
...

eine temporäre Datei erzeugen, die genau die gerade zu bearbeitenden Sätze enthält und schnell genug sein sollte
das sieht gut aus, ist jedenfalls dreimal so schnell wie mein Versuch mit Perl ;-) face-wink
den Teil mit cat bis zum ersten '|' kann man auch weglassen und direkt die Ausgabe von head nach tail pipen.

Spricht etwas dagegen, keine temporäre Datei anzulegen, sondern die 500 Zeilen direkt an das PHP-Programm zu übergeben? Dazu bräuchte man ein kleines Shellskript welches dann auch das PHP-Programm aufruft.

Markus
Bitte warten ..
Mitglied: ottscho
08.03.2013 um 10:57 Uhr

Sind Einzeilig. Das sieht gut aus. So werden wir es probieren.
Bitte warten ..
Mitglied: ottscho
08.03.2013 um 10:59 Uhr
Zitat von @64748:
> Zitat von @Lochkartenstanzer:
> ...
>
>
> eine temporäre Datei erzeugen, die genau die gerade zu bearbeitenden Sätze enthält und schnell genug sein
sollte
das sieht gut aus, ist jedenfalls dreimal so schnell wie mein Versuch mit Perl ;-) face-wink
den Teil mit cat bis zum ersten '|' kann man auch weglassen und direkt die Ausgabe von head nach tail pipen.

Spricht etwas dagegen, keine temporäre Datei anzulegen, sondern die 500 Zeilen direkt an das PHP-Programm zu übergeben?
Dazu bräuchte man ein kleines Shellskript welches dann auch das PHP-Programm aufruft.

Markus

Nein, spricht nichts dagen.
Bitte warten ..
Mitglied: 64748
64748 (Level 2)
08.03.2013, aktualisiert um 12:05 Uhr
Zitat von @ottscho:
...
Nein, spricht nichts dagen.
ich wollte eigentlich genauer sagen: man reduziert damit die Anzahl der Dateiöffnungen um die Hälfte. Außerdem werden diese nur noch von head gemacht was viel schneller sein dürfte als mit PHP.

Interessantes Thema übrigens, mich würde interessieren, wenn es fertig ist, wie es mit der tatsächlichen Zeitersparnis gegenüber Eurem ersten Ansatz aussieht.

Markus
Bitte warten ..
Mitglied: Lochkartenstanzer
08.03.2013 um 11:05 Uhr
Zitat von @64748:
> Zitat von @Lochkartenstanzer:
> ...
>
den Teil mit cat bis zum ersten '|' kann man auch weglassen und direkt die Ausgabe von head nach tail pipen.

Normal hätte ich das als
geschrieben. :-) face-smile

Ich benutze gern cat, weil ich solche Ketten meist "interaktiv" aufbaue und so einfach ein weiteres "|" mit Befehlen zwischenreinsetzen kann, ohne die schon vorhanden Kette groß verändern zu müssen. iIn der endgültigen Variante kann man natürlich dann verschiedene Pipe-Stufen "wegkürzen".

lks
Bitte warten ..
Mitglied: Guenni
10.03.2013, aktualisiert um 17:45 Uhr
Hi ottscho,

sofern nur die Importroutine das Timeout-Problem verursacht:

- Definiere einen Zähler für alle Zeilen
- Definiere einen Wert für die Zeilen, die pro Import importiert werden sollen

Wenn der Zähler_für_alle_Zeilen modulo_dividiert Zeilen_pro_Import 0 ergibt . . .

- Importroutine aufrufen
- Zähler_für_alle_Zeilen auf 0 setzen

Anschließend werden die letzten Zeilen eingelesen(importiert).

Beispiel:


Gruß
Günni
Bitte warten ..
Mitglied: ottscho
11.03.2013 um 08:04 Uhr
Moin Zusammen,

danke noch mal für die vielen Inputs von euch.
Auf die Schnell konnte ich es nicht über eine Consolen Anwendung umsetzen. Problem ist, dass die PHP Datei innerhalb eines Plugin System läuft und die API der Shopschnittstelle dort aus einer anderen Classe geladen wird.
Dazu fehlt mir einfach das Knowhow.

Ich habe es nun mit einem Byte Datenzeiger umgesetzt (fseek). Somit fange ich immer genau an der Stelle an zu lesen, wo ich davor aufgehört habe. D.h. ich muss nicht immer alle Datensätze überspringen.

Als Consolen Script muss es aber früher oder später laufen. Da später mehrere Shops damit bedient werden sollten.
Dann ist es über ein PHP Script, welches über eine URL aufgerufen wird mit der Zeit zu unübersichtlich.

Danke euch...
Bitte warten ..
Heiß diskutierte Inhalte
Monitoring
Computer im Netzwerk auslesen zur Inventarisierung
imebroVor 1 TagFrageMonitoring14 Kommentare

Hallo, für meine IT-Dokumentation muss ich nun auch unsere rund 15 PCs inventarisieren. Daher hätte ich gerne ein Programm, mit dem ich die wichtigsten ...

Windows 7
Aktivierung Windows
gelöst KanrishaVor 1 TagFrageWindows 714 Kommentare

Moin Admins, ich wollte mein Windows 7 mit einem Key den ich gekauft habe aktivieren. Da kam immer dieser FehlerCode was kann ich dagegen ...

Windows Server
Aufgabenplanung PowerShell Skript startet nicht
shooanVor 21 StundenFrageWindows Server33 Kommentare

Hallo Zusammen, ich habe ein Skript bekommen das ich gerne so einstellen will das dieses beim Start des Exchangeservers aktiviert werden soll. Ein Ausführung ...

Festplatten, SSD, Raid
Raid Level mischen auf einem Controller
DJBreezerVor 1 TagFrageFestplatten, SSD, Raid9 Kommentare

Hi, ich folge dem Ansatz, RAID Level auf dem selben Controller nicht zu mischen. Das heißt ich habe keine Controller im Einsatz, auf denen ...

Internet
Webcam oder IPcam aus dem Internet erreichbar?
dertowaVor 20 StundenFrageInternet16 Kommentare

Hallo zusammen, mal eine spezielle Frage, vielleicht kann jemand einen Dienst aufgrund guter Erfahrung empfehlen. Die Hündin einer guten Bekannten bekommt Nachwuchs und dafür ...

Exchange Server
Hosted Exchange von Ionos
it-blzVor 1 TagFrageExchange Server7 Kommentare

Hallo, wir möchten eventuell "Hosted Exchange" von Ionos nutzen. Leider kann ich die "Verwaltungsoberflächen" nicht vor Vertragsabschluss probieren und die Aussagen darüber sind wenig ...

Windows Netzwerk
Computername erneut vergeben?
gelöst malkieVor 1 TagFrageWindows Netzwerk10 Kommentare

Guten Morgen, wir haben in der Firma Computernamen nach dem Muster: PC-Abteilung-Nummer (PC-IT-1) So, aktuell habe ich mal gelernt ganz früher, dass man den ...

Netzwerke
2 verschiedene VPN für zu Hause
gelöst Reamer76Vor 1 TagFrageNetzwerke6 Kommentare

Hallo zusammen, da wir nun bald Glasfaser bekommen, brauche ich mal Hilfe von euch. Zustand jetzt (privat zu Hause): - Fritzbox LAN= 2PC`s und ...