Hallo zusammen, ich importiere unsere Kategorien mittels lokalem Zugriff auf die REST API. Der Ablauf: - csv einlesen - Kategorien per QueryBuilder aus dem Shop holen - falls Shop-Kategorie nicht in csv => deaktivieren Eigentlicher Import/Update der csv-Datei: - prüfen, ob Kategorie vorhanden => nein, dann anlegen => ja, dann prüfen ob aktualisiert werden muss ===> nein, nichts tun ===> ja, dann aktualisieren Hier der Code: foreach($cat as &$c) { try { set\_time\_limit(120); $changed = date("Y-m-d H:i:s", strtotime($c['changed'])); // Kategorie im Shop vorhanden? $sql = "SELECT `id` FROM `s_categories` WHERE `id`=?"; if(Shopware()-\>Db()-\>fetchOne($sql,$c['id'])) { // JA $sql = "SELECT `changed` FROM `s_categories` WHERE `id`=?"; $changed\_db = Shopware()-\>Db()-\>fetchOne($sql,$c['id']); // Änderung seit letztem Update ? // ja = Update, nein = nichts tun if((strtotime($changed)-strtotime($changed\_db)) \> 0) { // Update im Shop $catRes-\>update($c['id'], array( 'name' =\> $c['description'], 'cmsHeadline' =\> $c['description'], 'position' =\> $c['position'], 'active' =\> $c['active'], 'parent' =\> $c['parentId'], 'cmsText' =\> $c['text'], 'metaDescription' =\> $c['text'], 'changed' =\> $changed )); } } else { // NEIN, nicht im Shop // Anlage im Shop $catRes-\>create(array( 'id' =\> $c['id'], 'name' =\> $c['description'], 'cmsHeadline' =\> $c['description'], 'position' =\> $c['position'], 'active' =\> $c['active'], 'parent' =\> $c['parentId'], 'cmsText' =\> $c['text'], 'metaDescription' =\> $c['text'], 'changed' =\> $changed )); } } catch (Exception $e) {} }
Kategoriebaum 1 hat etwa 100 Kategorien mit max 3 Ebenen, also Kat1 -> Kat2 -> Kat3. Hier läuft der Erst-Import nicht einmal 10 Sekunden, das ist top. Kategoriebaum 2 hat etwa 800 Kategorien mit bis zu 6 Ebenen. Hierfür braucht der Erst-Import dann ca. 3 Stunden. Bevor ich testweise set_time_limit(120) eingebaut hatte, kam es auch gelegentlich zu einem TimeOut durch CategoryDenormalization (60 Sekunden). Woran liegt es, dass der Import bei Kategoriebaum 2 so lange dauert? Anzahl der Kategorien? Tiefe/Verschachtelung des Kategoriebaumes? Und wie kann ich das optimieren? Bin für jede Hilfe dankbar!
hi, du hast am Ende sehr viele Anfrage auf die DB. Für jede Kategorie macht du 2 Abfragen. Diese könntest du schon mal halbieren wenn du statt // Kategorie im Shop vorhanden? $sql = "SELECT `id` FROM `s_categories` WHERE `id`=?"; if(Shopware()-\>Db()-\>fetchOne($sql,$c['id'])) { // JA $sql = "SELECT `changed` FROM `s_categories` WHERE `id`=?"; $changed\_db = Shopware()-\>Db()-\>fetchOne($sql,$c['id']);
z.B (ungetestet): // Kategorie im Shop vorhanden? $sql = "SELECT `id`,`changed` FROM `s_categories` WHERE `id`=?"; $cat = Shopware()-\>Db()-\>fetchRow($sql,$c['id']); if($cat['id']) { // JA $changed\_db = $cat['changed'];
Du könntest das ganze aber auch noch auf eine Anfrage auf die Db reduzieren wenn du deine IDs vorher in ein Array schreibst und dann dein Statement mit dem IN-Operator stellst WHERE column\_name IN (value1,value2,...);
Ich glaube das würde das ganze um einiges beschleunigen. Zudem könntest du anstatt direkt eine Anfrage an die Db zustellen die entsprechende Resource bemühen. Viele Grüße
Ja, wie oben gesagt vielleicht mal die lokale API einbeziehen, als Versuch. Ich hab deinen Code mal aufgeräumt, ist aber ungetestet (!) weil gerade nur runtergeschrieben (!) set\_time\_limit(120); foreach($cat as $c) { $changed = date("Y-m-d H:i:s", strtotime($c['changed'])); $catArray = $this-\>buildCategoryArray($c, $changed); try { $cat = $catRes-\>getOne($c['id']); } catch (\Exception $e) { // cat doesnt exist } // if (!empty($cat) { if((strtotime($changed)-strtotime($cat['changed'])) \> 0) { $this-\>updateCategory($c['id'], $catArray); } else { // no update required } } else { $this-\>createCategory($catArray); } } private function buildCategoryArray($c, $changed) { return array( 'name' =\> $c['description'], 'cmsHeadline' =\> $c['description'], 'position' =\> $c['position'], 'active' =\> $c['active'], 'parent' =\> $c['parentId'], 'cmsText' =\> $c['text'], 'metaDescription' =\> $c['text'], 'changed' =\> $changed ); } private function updateCategory($catId, $category) { try { $catRes-\>update($catId, $category); } catch (\Exception $) { // failed update } } private function createCategory($category) { try { $catRes-\>create($category); } catch (\Exception $) { // failed creation } }
Vielen Dank euch Beiden. Leider liefert getOne() das Änderungsdatum nicht mit. Mit ein paar kleinen Änderungen lief Niklas’ Code ca. 45 Minuten, also schon deutlich schneller. Damit kann ich gut leben! foreach ($categories as $c) { set\_time\_limit(120); $changed = date("Y-m-d H:i:s", strtotime($c['changed'])); $catArray = $this-\>buildCategoryArray($c, $changed); try { $sql = "SELECT `changed` FROM `s_categories` WHERE `id`=?"; $changed\_db = Shopware()-\>Db()-\>fetchOne($sql, $c['id']); } catch (\Exception $e) {} if(!empty($changed\_db)) { if((strtotime($changed) != strtotime($changed\_db))) { $this-\>updateCategory($c['id'], $catArray); } } else { $this-\>createCategory($catArray); } } private function buildCategoryArray($c, $changed) { return array( 'id' =\> $c['id'], 'name' =\> $c['description'], 'cmsHeadline' =\> $c['description'], 'position' =\> $c['position'], 'active' =\> $c['active'], 'parent' =\> $c['parentId'], 'cmsText' =\> $c['text'], 'metaDescription' =\> $c['text'], 'changed' =\> $changed ); } private function updateCategory($catId, $category) { $catRes = \Shopware\Components\Api\Manager::getResource('Category'); try { $catRes-\>update($catId, $category); } catch (\Exception $e) {} } private function createCategory($category) { $catRes = \Shopware\Components\Api\Manager::getResource('Category'); try { $catRes-\>create($category); } catch (\Exception $e) {} }