Top-Themen

Aktuelle Themen (A bis Z)

Administrator.de FeedbackApache ServerAppleAssemblerAudioAusbildungAuslandBackupBasicBatch & ShellBenchmarksBibliotheken & ToolkitsBlogsCloud-DiensteClusterCMSCPU, RAM, MainboardsCSSC und C++DatenbankenDatenschutzDebianDigitiales FernsehenDNSDrucker und ScannerDSL, VDSLE-BooksE-BusinessE-MailEntwicklungErkennung und -AbwehrExchange ServerFestplatten, SSD, RaidFirewallFlatratesGoogle AndroidGrafikGrafikkarten & MonitoreGroupwareHardwareHosting & HousingHTMLHumor (lol)Hyper-VIconsIDE & EditorenInformationsdiensteInstallationInstant MessagingInternetInternet DomäneniOSISDN & AnaloganschlüsseiTunesJavaJavaScriptKiXtartKVMLAN, WAN, WirelessLinuxLinux DesktopLinux NetzwerkLinux ToolsLinux UserverwaltungLizenzierungMac OS XMicrosoftMicrosoft OfficeMikroTik RouterOSMonitoringMultimediaMultimedia & ZubehörNetzwerkeNetzwerkgrundlagenNetzwerkmanagementNetzwerkprotokolleNotebook & ZubehörNovell NetwareOff TopicOpenOffice, LibreOfficeOutlook & MailPapierkorbPascal und DelphiPeripheriegerätePerlPHPPythonRechtliche FragenRedHat, CentOS, FedoraRouter & RoutingSambaSAN, NAS, DASSchriftartenSchulung & TrainingSEOServerServer-HardwareSicherheitSicherheits-ToolsSicherheitsgrundlagenSolarisSonstige SystemeSoziale NetzwerkeSpeicherkartenStudentenjobs & PraktikumSuche ProjektpartnerSuseSwitche und HubsTipps & TricksTK-Netze & GeräteUbuntuUMTS, EDGE & GPRSUtilitiesVB for ApplicationsVerschlüsselung & ZertifikateVideo & StreamingViren und TrojanerVirtualisierungVisual StudioVmwareVoice over IPWebbrowserWebentwicklungWeiterbildungWindows 7Windows 8Windows 10Windows InstallationWindows MobileWindows NetzwerkWindows ServerWindows SystemdateienWindows ToolsWindows UpdateWindows UserverwaltungWindows VistaWindows XPXenserverXMLZusammenarbeit

While Schleife - Zu bestimmter Stelle springen

Frage Entwicklung PHP

Mitglied: ottscho

ottscho (Level 2) - Jetzt verbinden

08.03.2013 um 08:09 Uhr, 3102 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.


01.
$row = 1; // Anzahl der Arrays 
02.
			$handle = fopen ("upload/artikel.csv","r"); // Datei zum Lesen �ffnen 
03.
			// Die erste Zeile mit den Spaltennamen auslesen 
04.
			$data = fgetcsv ($handle, 100000, ";"); 
05.
			if(is_array($data)) { 
06.
			   foreach($data AS $cellNr => $cellName) { 
07.
				   $cellNamesArray[$cellNr] = $cellName
08.
09.
10.
			$return=false;		 
11.
			while ( ($data = fgetcsv ($handle, 100000, ";")) !== FALSE ) { // Daten werden aus der Datei 
12.
				$num = count ($data); // Felder im Array $data 
13.
				//var_dump('row: '.$row); 
14.
				//var_dump('offset: '.$offset); 
15.
				//var_dump('step: '.$step); 
16.
				 
17.
				if ($row <= $offset) { 
18.
					$row++; // Anzahl der Arrays wird 
19.
					continue
20.
21.
				if ($row > $offset+$step) { 
22.
					$return=true; 
23.
					break
24.
25.
				$row++; // Anzahl der Arrays wird 
26.
				$count = 0; 
27.
				for ($c=0; $c < $num; $c++) { // FOR-Schleife, um Felder des Arrays auszugeben 
28.
					$feld[$cellNamesArray[$c]] = $data[$c]; 
29.
					$count++;	 
30.
31.
				 
32.
				//**********************// 
33.
				//*** IMPORT Routine ***// 
34.
				//**********************// 
35.
 
36.
37.
                                



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".

01.
 				if ($row <= $offset) { 
02.
 					$row++; // Anzahl der Arrays wird 
03.
 					continue
04.
05.
 				if ($row > $offset+$step) { 
06.
 					$return=true; 
07.
 					break
08.
09.
 				$row++; // Anzahl der Arrays wird
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
01.
$return = `nohup php mein_scipt.php >stdout.log 2>stderr.log </dev/null & echo $!`;
so bekommst du die Prozess ID zurück und hast die Ausgaben in Log Dateien.
Bitte warten ..
Mitglied: 64748
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

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

cat csv-datei | head -n start+500 | tail -n 500 >temp.csv
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
08.03.2013, aktualisiert um 10:57 Uhr
Zitat von Lochkartenstanzer:
...
> cat csv-datei | head -n start+500 | tail -n 500 >temp.csv 
> 
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
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
cat csv-datei | head -n start+500 | tail -n 500 >temp.csv
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:
> ...
>
> > cat csv-datei | head -n start+500 | tail -n 500 >temp.csv 
> > 
>
> 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
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
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:
> ...
>
> > cat csv-datei | head -n start+500 | tail -n 500 >temp.csv 
> > 
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
cat csv-datei | head -n start+500 | tail -n 500 | tee temp.cs
geschrieben.

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:

01.
<?php 
02.
$lines=0; 
03.
$max_lines=500; 
04.
$f=fopen("doku.txt","r"); 
05.
	while($line=fgets($f)){ 
06.
	 $line_arr[$lines]=$line; 
07.
	 $lines++; 
08.
		if($lines%$max_lines==0){ 
09.
		 echo "// Importroutine: "; 
10.
		 echo $lines.' Zeilen werden importiert.<br>'; 
11.
			$lines=0; 
12.
13.
14.
	/* 
15.
	* Restliche Zeilen importieren 
16.
	*/ 
17.
	while($line=fgets($f)){ 
18.
	 $line_arr[$lines]=$line; 
19.
	 $lines++; 
20.
21.
	if($lines>0){ 
22.
	 echo "// Importroutine: "; 
23.
	 echo $lines.' Zeilen werden importiert.<br>'; 
24.
25.
fclose($f); 
26.
?>
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 ..
Ähnliche Inhalte
Batch & Shell
Text an bestimmter Stelle einfügen
gelöst Frage von noob-xBatch & Shell2 Kommentare

Hallo bin mal wieder am Basteln, komm aber nicht weiter wie stelle ich es an dass nummer 1 immer ...

Entwicklung
Programmierung - In Textdatei an einer bestimmten Stelle einen bestimmten Wert eintragen
gelöst Frage von JimStarEntwicklung1 Kommentar

Guten Morgen zusammen, habe ein kleines Problem: Ich soll ein Script schreiben, welches durch ausführen eine bestimmte Datei bearbeitet. ...

Microsoft Office
Zelleninhalte mit bestimmtem Abstand transponieren mit Schleife
gelöst Frage von KrenzJMicrosoft Office4 Kommentare

Guten Mittag alle miteinander, und nun direkt zu meiner Frage. Ich möchte auch noch daraufhin weisen, dass ich leider ...

VB for Applications
VBS Textzeile in fsx.cfg Datei an bestimmte Stelle einfügen
gelöst Frage von aletriVB for Applications6 Kommentare

Guten Abende Leute Mit dem hier aufgeführten Script möchte ich den Text "AutogenDescriptionsFilename=AutogenDescriptions_EFRO.xml" einfügen was soweit auch mit der ...

Neue Wissensbeiträge
Sicherheits-Tools

Achtung: Sicherheitslücke im FortiClient VPN-Client

Tipp von kgborn vor 1 StundeSicherheits-Tools

Ich weiß nicht, wie häufig die NextGeneration Endpoint Protection-Lösung von Fortinet in deutschen Unternehmen eingesetzt wird. An dieser Stelle ...

Internet

USA: Die FCC schaff die Netzneutralität ab

Information von Frank vor 15 StundenInternet2 Kommentare

Jetzt beschädigt US-Präsident Donald Trump auch noch das Internet. Der neu eingesetzte FCC-Chef Ajit Pai ist bekannter Gegner einer ...

DSL, VDSL

ALL-BM200VDSL2V - Neues VDSL-Modem mit Vectoring von Allnet

Information von Lochkartenstanzer vor 19 StundenDSL, VDSL1 Kommentar

Moin, Falls jemand eine Alternative zu dem draytek sucht: Gruß lks

Windows 10

Microsoft bestätigt DMA-Policy-Problem in Win10 v1709

Information von DerWoWusste vor 19 StundenWindows 10

Wer sein Gerät mit der DMA-Policy absichert, bekommt evtl. Hardwareprobleme in v1709 von Win10. Warum? Weil v1709 endlich "richtig" ...

Heiß diskutierte Inhalte
Netzwerkmanagement
Mehrere Netzwerkadapter in einem PC zu einem Switch zusammenfügen
Frage von prodriveNetzwerkmanagement21 Kommentare

Hallo zusammen Vorweg, ich konnte schon einige IT-Probleme mit Hilfe dieses Forums lösen. Wirklich klasse hier! Doch für das ...

Hardware
Links klick bei Maus funktioniert nicht
gelöst Frage von Pablu23Hardware16 Kommentare

Hallo erstmal. Ich habe ein Problem mit meiner relativ alten maus jedoch denke ich nicht das es an der ...

Windows Server
Anmeldung direkt am DC nicht möglich
Frage von ThomasGrWindows Server16 Kommentare

Hallo, ich habe bei unserem Server 2016 Standard ein Problem. Keine Ahnung wie das auf einmal passiert ist. Ich ...

TK-Netze & Geräte
VPN-fähige IP-Telefone
Frage von the-buccaneerTK-Netze & Geräte14 Kommentare

Hi! Weiss noch jemand ein VPN-fähiges IP-Telefon mit dem man z.B. einen Heimarbeitsplatz gesichert anbinden könnte? Habe nur einen ...