Armin: Datenabgleich dBase -> SQL dauert 4 Stunden?!

Hi zusammen,

ich hab ein Problem mit einem PHP-Script das einen täglichen Datenabgleich eines Artikelstammes vornehmen soll.
Das Script ladet vom Server eines Lieferanten ein .zip-File runter, entpackt dieses. So entstehet ein dBase-File das meine mySQL-DB auf den aktuellen Stand bringen soll.
Dazu verwende ich zuerst ein Select um heraus zu finden ob der Datensatz bereits existiert. Wenn ja, wird er mit einem Update aktualisiert, wenn nein wird er mit einem Insert angelegt.

---------------------------------------------------------------
echo "-> READ DBASE-FILE " . $EXTFILE . "...\n";
if(!$dbh = dbase_open($EXTFILE, 0))
{
  echo "<- CAN'T OPEN DBASE-FILE " . $EXTFILE . "\n\n";
}
else
{
  $num_fields = dbase_numfields ($dbh);
  $num_rows   = dbase_numrecords($dbh);
  echo "<- READING DBASE FILE WITH " . $num_fields . " FIELDS IN " . $num_rows . " ROWS...\n";
  $i = 1;
  $isi = 0;
  $isu = 0;
  while($i <= $num_rows)
   {
    $rr = dbase_get_record_with_names($dbh, $i);
    // hier werden die variabeln dann noch gesetzt.
    $sql = "SELECT products\_id FROM " . $ASE\_DBTABL\_PROD . " WHERE products\_dist LIKE '" . $DIST . "' AND products\_anr LIKE '" . $DIST . $products_anr . "' LIMIT 0 , 1";
    $result = mysql_query($sql, $ASE_DBCONN1);
    if(mysql_num_rows($result) > 0)
     {
      $sql  = "UPDATE " . $ASE\_DBTABL\_PROD . " SET ";
      $sql .= " products\_hnr = '" . $products_hnr . "', products\_mfg = '" . $products_mfg . "', products\_grp1 = '" . $products_grp1 . "', products\_grp2 = '" . $products_grp2 . "', products\_grp3 = '" . $products_grp3 . "', products\_dsc1 = '" . $products_dsc1 . "', products\_dsc2 = '" . $products_dsc2 . "', products\_war = '" . $products_war . "', products\_pprc = '" . $products_pprc . "', products\_sprcn = '" . $products_sprcn . "', products\_sprcb = '" . $products_sprcb . "', products\_tax = '" . $products_tax . "', products\_dat1 = '" . $products_dat1 . "', products\_aprc = '" . $products_aprc . "', products\_adat = '" . $products_adat . "', products\_pdf = '" . $products_pdf . "', products\_img = '" . $products_img . "', products\_wght = '" . $products_wght . "', products\_ean = '" . $products_ean . "', products\_lst = NOW() ";
      $sql .= " WHERE products\_dist LIKE '" . $DIST . "' AND products\_anr LIKE '" . $DIST . $products_anr . "'";
      $isu++;
     }
    else
     {
      $sql  = "INSERT INTO " . $ASE\_DBTABL\_PROD . " (products\_dist, products\_anr, products\_hnr, products\_mfg, products\_grp1, products\_grp2, products\_grp3, products\_dsc1, products\_dsc2, products\_war, products\_pprc, products\_sprcn, products\_sprcb, products\_tax, products\_stor, products\_dat1, products\_dat2, products\_aprc, products\_adat, products\_pdf, products\_img, products\_wght, products\_ean, products\_crt, products\_lst)";
      $sql .= "VALUES ('" . $DIST . "', '" . $DIST . $products_anr . "', '" . $products_hnr . "', '" . $products_mfg . "', '" . $products_grp1 . "', '" . $products_grp2 . "', '" . $products_grp3 . "', '" . $products_dsc1 . "', '" . $products_dsc2 . "', '" . $products_war . "', '" . $products_pprc . "', '" . $products_sprcn . "', '" . $products_sprcb . "', '" . $products_tax . "', '" . $products_stor . "', '" . $products_dat1 . "', '" . $products_dat2 . "', '" . $products_aprc . "', '" . $products_adat . "', '" . $products_pdf . "', '" . $products_img . "', '" . $products_wght . "', '" . $products_ean . "', '" . $products_crt . "', NOW())";
      $isi++;
     }
    $result = mysql_query($sql, $ASE_DBCONN1);
    $i++;
   }
}
---------------------------------------------------------------

Das funktioniet soweit auch, leider dauert es viel zu lange. Auf einem Athlon64 3,0 mit 1 GB Ram kann das schon 30-40 Minuten dauern. Auf dem Webserver, der längsamer ist und den ich mit mit anderen Sites teilen muss hab ich teilweise 2-3 Stunden gebraucht, und dabei den Server komplett ausgelastet.

Hat wer eine Idee, wie man das ganz optimieren kann? Das Problem scheint eindeutig am SQL-Server zu liegen und nicht an PHP. Soweit mir aufgefallen ist, scheint das Problem beim Select oder Update zu liegen, denn wenn ich die DB einfach vorher leere und alles Inserte gehts entschieden schneller.

Bin für jeden Tipp dankbar,
   Armin

  1. Hallo Armin,

    Hat wer eine Idee, wie man das ganz optimieren kann? Das Problem scheint eindeutig am SQL-Server zu liegen und nicht an PHP. Soweit mir aufgefallen ist, scheint das Problem beim Select oder Update zu liegen, denn wenn ich die DB einfach vorher leere und alles Inserte gehts entschieden schneller.

    Update und Select können natürlich recht lange dauern, besonders, wenn es um große Tabellen geht. Das ist so ohne genaue Angabe schwer abschätzbar.

    Hast du schon daran einen Index oder auch mehrere zu setzen auf diejenigen Spalten, die nicht Schlüsselspalten sind, aber in den "WHERE"-Klauseln vorkommen? Wenn diese Spalteninhalte eine hohe Granularität aufweisen, wirkt das oft Wunder.

    Gruß Mia

  2. Hi,

    $sql = "SELECT products\_id FROM " . $ASE\_DBTABL\_PROD . " WHERE products\_dist LIKE '" . $DIST . "' AND products\_anr LIKE '" . $DIST . $products_anr . "' LIMIT 0 , 1";

    Brauchst Du wirklich LIKE? Oder würde es = auch tun?
    Du erwartest ja offensichtlich nur ein einziges Ergebnis (LIMIT 0,1) ...
    Außerdem schreibst Du die Werte später direkt so in die Datenbank - die Abfrage auf Ähnlichkeit (LIKE) ist also wohl eher sinnlos.

    Sind die Spalten products_dist und products_anr indiziert?

    $sql  = "UPDATE " . $ASE\_DBTABL\_PROD . " SET ";

    [...]

    $sql .= " WHERE products\_dist LIKE '" . $DIST . "' AND products\_anr LIKE '" . $DIST . $products_anr . "'";

    Hier fragst Du wieder über products_dist und products_anr ab - Du hattest vorher aber schon die (vermutlich eindeutige, weil autoincrement und Primary Key?) id ermittelt - es bietet sich hier also an, die id wiederzuverwenden.

    cu,
    Andreas

    --
    Warum nennt sich Andreas hier MudGuard?
    Schreinerei Waechter
    Fachfragen per E-Mail halte ich für unverschämt und werde entsprechende E-Mails nicht beantworten. Für Fachfragen ist das Forum da.
  3. hi,

    Hat wer eine Idee, wie man das ganz optimieren kann? Das Problem scheint eindeutig am SQL-Server zu liegen und nicht an PHP. Soweit mir aufgefallen ist, scheint das Problem beim Select oder Update zu liegen, denn wenn ich die DB einfach vorher leere und alles Inserte gehts entschieden schneller.

    kannst du REPLACE verwenden anstatt dich vom SELECT abhängig für UPDATE oder INSERT zu entscheiden ...?

    gruß,
    wahsaga

    --
    /voodoo.css:
    #GeorgeWBush { position:absolute; bottom:-6ft; }