Thread MySQL Verständnisfrage: 100 Datensätze in eiem Schwung eintragen (17 answers)
Opened by olruebe01 at 2007-01-03 18:47

olruebe01
 2007-01-05 15:59
#35048 #35048
User since
2006-01-19
192 Artikel
BenutzerIn
[default_avatar]
Hallo Nepos, hallo pq,

danke für Eure hilfe.
Ich setze jetzt die von Euch vorgeschlagene Version um. Also ein prepare und dann jedesmal in der Schleife ein Execute.

Nun habe ich ein neues PRoblem:
Ich lese per Script die csv-Dateien Zeilenweise ein, ändere diese so wie ich es brauche und trage sie dann per Execute ein. Den prepare habe ich vor der Schleife gesetzt...

Vorteil: Der benötigte Arbeitsspeicher ist jetzt 99% geringer. Juhu...

Aber: In der DB sind 3,6 Mio Zeilen. Nun habe ich eine aktualisierte CSV bekommen, lösche alle alten (betroffenen) Zeilen, um die neuen Zeilen einzulesen. So als Richtwert: Bei einer Aktualisierung gibt es etwa 300.000 neue Zeilen (mal mehr, mal weniger).
Das Script erzeugt einen I/O-Wait von 80-95% und einen LoadAverage von 6-8 (normal habe ich etwa 0,5). Also denke ich "das kann es nicht sein" und kille dieses Script. Aber: Die MySQL-Befehle werden noch STUNDEN weiter ausgeführt und der I/O WAIT bleibt hoch.

Im Klartext: Nachdem ich das Script gekillt habe, werden noch STUNDEN Daten in die DB geschrieben und der I/O-Wait bleibt hoch. Mein Gedanke: Kann es sein, dass das Script die SQL-Befehle schneller ausgibt, als diese von Mysql abgefrühstückt werden können? Ist es also möglich, dass die ganzen MySQL-Befehle in einer Warteschlange landen und auch nach Beendung des Scripts weiter ausgeführt werden?

Wo kann ich nach Fehlern suchen, wie mache ich es besser?

Mal abgesehen von einem eventuellem Fehler habe ich 2 Gedanken:
Vielleicht ist die Tabelle einfach inzwischen so groß, dass es halt seine Zeit dauert???
Idee: Ich lege eine zweite identische Tabelle an, trage alle neuen Daten hier ein. Da die Tabelle leer ist, könnte das schneller gehen(??). Nachdem alle Daten drin sind, kopiere ich die Zeilen von einer Tabelle in die andere...

Idee2: Ich lese die CSV per Script ein, ändere die Werte wie ich sie brauche und schreibe die Datei wieder als CSV auf die Festplatte. Danach lade die Daten per LOAD INFILE in die DB.

Am liebsten würde ich natürlich einen Fehler entdecken und beseitigen :-)

Hier mal der relevante Code:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
### Zuerst wurden neue Daten gefunden, geladen und lokal gespeichert. Dies klappt (sehr schnell)

sub eintragen{   ### Wird bei jeder aktualisierten Datei aufgerufen...

$file = "produktdaten/$PartnerID.dat";
print "FILE: $PartnerID<BR>";


$dbh->do (qq~DELETE  FROM `Produktdaten` WHERE `PartnerID` = '$PartnerID'~); ### Alte Einträge dieses Partners löschen



my $sql = qq{insert into  Produktdaten(PartnerID, Bezeichnung,Kurzbeschreibung,Beschreibung,Preis,alterPreis,Waehrung,Keywords,Bild_kl,Bild_mittel,Bild_gross,Deeplink,gueltig_von,gueltig_bis,status,lieferzeit,Bedingungen,Hersteller,Brand,Partner_Kategorie, aktualisiert, laufendeNummer) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)};
my $stheintragen = $dbh->prepare( $sql );



open(FILE, "$file") or die "Could not open $file: $!\n";
while (defined (my $ZEILE = <FILE>)) { ### Zeilenweise neue Daten aus der CSV einlesen


......
Nun werden die Einzelnen Zeilen bearbeitet / angepasst. Z.B. Datum in Sekunden wandeln, Komma in Punkt wandeln, etc...
......



(undef, undef, $MerchantProductNumber, $Bezeichnung, $Preis, $alterPreis, $Waehrung, $update, $gueltig_von, $gueltig_bis, $kurzbeschreibung, $Beschreibung, $status, $Partner_Kategorie, undef, $Bild_kl, $Bild_mittel, $Bild_gross, $Hersteller, $Deeplink, undef, undef, $lieferzeit, $Bedingungen, $EAN) = split(/<SPLIT>/, $ZEILE);



if ($update =~ " "){   ### Zur Sicherheit. Einige Datumsangaben haben ein anderes Format
($datum, undef) = split(/ /, $update);
&sekunden;
$update = $sekunden;
}



if ($gueltig_von =~ " "){ ### Zur Sicherheit. Einige Datumsangaben haben ein anderes Format
($datum, undef) = split(/ /, $gueltig_von);
&sekunden;
$gueltig_von = $sekunden;
}



if ($gueltig_bis =~ " "){ ### Zur Sicherheit. Einige Datumsangaben haben ein anderes Format
($datum, undef) = split(/ /, $gueltig_bis);
&sekunden;
$gueltig_bis = $sekunden;
}



$laufendeNummer++;



$stheintragen->execute($PartnerID, $Bezeichnung,$kurzbeschreibung,$Beschreibung,$Preis,$alterPreis,$Waehrung,$Keywords,$Bild_kl,$Bild_mittel,$Bild_gross,$Deeplink,$gueltig_von,$gueltig_bis,$status,$lieferzeit,$Bedingungen,$Hersteller,$Brand, $Partner_Kategorie, $update, $ID)|| die "Database connection not made: $DBI::errstr";



} ## Ende der ZEILE



$stheintragen->finish();



} ## ENDE sub -> Ende der neuen Datei


Mache ich was falsch oder dauert das einfach? Wie kann ich verhindern, dass die ganzen SQL-Befehler in einer "Warteschleife" landen?

View full thread MySQL Verständnisfrage: 100 Datensätze in eiem Schwung eintragen