Timeout bei SELECT * FROM

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Timeout bei SELECT * FROM

    Hallo Leute,

    ich stehe mal wieder vor einem Problem welches ich mir nicht erklären kann.

    Ich möchte Produktdaten aus einer CSV-Datei in eine Datenbank importieren. Es sind ca. 100.000 Produkte. Um dabei nicht in einen Timeout rein zu laufen, importiere ich Pakete mit je 1.000 Produkte. Das heisst, nach jedem 1.000sten Produkt ruft sich das Script immer wieder selber auf, solang bis alle Produktdaten aus der CSV abgearbeitet sind - ich nenne diese Selbstaufrufe jetzt einfach mal "Prozesse".

    Bei diesen "Prozessen" wird geprüft, ob das jeweilige Produkt schon existiert - wenn ja, wird ein UPDATE des Produkts ausgeführt, wenn nein wird ein INSERT in eine temoräre Datenbank ausgeführt. Und genau bei diese Prüfung liegt mein Problem. Von Prozess zu Prozess wird die Prüfung auf Existens des Produkts immer langsamer bis hin zum Timeout.

    Lasse ich die Prüfung weg und importiere die Produkte in die temporäre Datenbank, arbeiten die Prozesse alle 100.000 Produkte ohne Probleme ab.
    Kann mir jemend dieses "Ausbremsen" erklären?

    Hier mal das Snippet:

    Quellcode

    1. // Prüfen ob der Datensatz schon existiert. Wenn ja, updaten ansonsten neu schreiben
    2. $database->db_query("pruefung", "SELECT * FROM ".$mysql_table_produkte_test." WHERE ProgramID = '".$ProgramID."' AND MerchantProductNumber = '".$MerchantProductNumber."' LIMIT 1");
    3. if($database->db_get_num_results("pruefung") == 1)
    4. {
    5. // Daten in Produkt-Datenbank updaten
    6. $database->db_query("updaten", "UPDATE ".$mysql_table_products." SET ProductName = '".$ProductName."', ProductPrice = '".$ProductPrice."', ProductPriceOld = '".$ProductPriceOld."', CurrencySymbolOfPrice = '".$CurrencySymbolOfPrice."', ValidFromDate = '".$ValidFromDate."', ValidToDate = '".$ValidToDate."', ProductShortDescription = '".$ProductShortDescription."', ProductLongDescription = '".$ProductLongDescription."', ImageSmallURL = '".$ImageSmallURL."', ImageMediumURL = '".$ImageMediumURL."', ImageLargeURL = '".$ImageLargeURL."', ZanoxProductLink = '".$ZanoxProductLink."', DeliveryTime = '".$DeliveryTime."', TermsOfContract = '".$TermsOfContract."', ProductEAN = '".$ProductEAN."', ISBN = '".$ISBN."', ShippingAndHandling = '".$ShippingAndHandling."', ShippingAndHandlingCost = '".$ShippingAndHandlingCost."', kategorie_id = '".$kategorie_id."' WHERE ProgramID = '".$ProgramID."' AND MerchantProductNumber = '".$MerchantProductNumber."' LIMIT 1");
    7. }
    8. else
    9. {
    10. // Daten in temporäre Datenbank schreiben
    11. $database->db_query("einfuegen", "INSERT INTO ".$mysql_table_products_temp." (ProgramID, MerchantName, MerchantProductNumber, ProductName, ProductPrice, ProductPriceOld, CurrencySymbolOfPrice, ValidFromDate, ValidToDate, ProductShortDescription, ProductLongDescription, ImageSmallURL, ImageMediumURL, ImageLargeURL, ProductManufacturerBrand, ZanoxProductLink, DeliveryTime, TermsOfContract, ProductEAN, ISBN, ShippingAndHandling, ShippingAndHandlingCost, kategorie_id, status) VALUES ('$ProgramID', '$MerchantName', '$MerchantProductNumber', '$ProductName', '$ProductPrice', '$ProductPriceOld', '$CurrencySymbolOfPrice', '$ValidFromDate', '$ValidToDate', '$ProductShortDescription', '$ProductLongDescription', '$ImageSmallURL', '$ImageMediumURL', '$ImageLargeURL', '$ProductManufacturerBrand', '$ZanoxProductLink', '$DeliveryTime', '$TermsOfContract', '$ProductEAN', '$ISBN', '$ShippingAndHandling', '$ShippingAndHandlingCost', '$kategorie_id', 'Aktiv')");
    12. }
    Alles anzeigen

    Schon mal Danke.

    Grüße KMD
  • KMD schrieb:

    behebt aber nicht das Problem, dass bei Prozess zu Prozess der Aufruf immer langsamer wird.

    Ja doch, weil umso mehr Produkte in der Tabelle sind umso langsamer wird eben die Abfrage ob das Produkt schon drin ist. Außer du hast eh schon sovile Produkte drin, dass die 100.000 nicht mehr ins Gewicht fallen, aber ich denke dann hättest du von vorneherein Probleme mit dem Timeout ;)
  • @Szabo
    Nein, habe ich leider nicht. :(

    @Rondrer
    Das Problem hat sich mit dem Indexieren scheinbar gelöst. :)

    Aber...
    Ja doch, weil umso mehr Produkte in der Tabelle sind umso langsamer wird eben die Abfrage ob das Produkt schon drin ist.
    Da gebe ich dir Recht. Aber in der DB befinden sich derzeit ca. 8.000 Produkte und in der CSV-Test-Datei sind die gleichen Produkte wie in der Datenbank (also ebenfalls 8.000 Produkte) - sollen also geupdatet werden. Demzuvolge werden es auch nicht mehr.
    Prinzipiell müsste also der zweite, dritte, vierte, usw Prozess genauso lange für die Prüfung brauchen wie der erste Prozess.
    Ich würde einfach gerne verstehen warum das so ist - auch wenn das Problem nun scheinbar gelöst ist. ;)

    Grüße KMD
  • Hm, wenn es nicht mehr Produkte werden ist das in der Tat seltsam.

    Ich hätte dafür nur eine Erklärung, das ist aber reine Spekulation:

    Wurden die Produkte in der gleichen Reihenfolge in die Datenbank geschrieben, wie sie in der CSV Datei stehen?
    Dann könnte es sein, dass wenn der die Datenbank durchsucht, auch nach dieser Reihenfolge vorgeht. D.h. die Produkte die oben in der CSV-Datei stehen werden viel früher gefunden als die, die weiter unten stehen. Dank des "Limit 1" muss er ja, sobalb er einen Treffer hat, den Rest der Tabelle nicht mehr durchsuchen.
    D.h. den ersten Eintrag in der CSV-Datei findet er sofort, da es auch der erste Eintrag in der Datenbank ist. Beim 8000. muss er erst die 7999 anderen durchsuchen.
    Ob das wirklich die Lösung des Problem ist, kannst du z.b. testen in dem du die CSV-Datei in umgekehrter Reihenfolge bearbeitest also von unten nach oben. Dann müsste, wenn meine Theorie stimmt, die verarbeitungszeit pro Prozess abnehmen, statt zuzunehmen. Oder du nimmst mal das "Limit 1" raus, dann sollte die Zeit konstant bleiben.

    Wie gesagt nur Spekulation, aber testen kann man's ja mal ;)