Neulich bin ich in einer älteren Version einer in Deutschland sehr beliebten Extension über einen lustigen kleinen Performance-Killer gestolpert: Es sollte ein Quote-Object anhand der ID geladen werden, das sah im Code folgendermaßen aus:
$quote = Mage::getModel('sales/quote')->getCollection()->getItemById($quote_id);
harmlos, oder? Nein!
Diese eine Zeile brauchte ca. 30 Sekunden, und das auf einem wirklich performanten Kundenserver.
Wie kommt’s?
In lib/Varien/Data/Collection.php finden wir folgendes:
/** * Retrieve item by id * * @param mixed $idValue * @return Varien_Object */ public function getItemById($idValue) { $this->load(); if (isset($this->_items[$idValue])) { return $this->_items[$idValue]; } return null; }
Zuerst wird die gesamte Collection geladen, und dann per Array-Lookup das richtige Element zurückgegeben. Die gesamte Collection laden bedeutete in diesem Fall 50.000 Quotes aus der Datenbank abholen, 50.000 mal den Konstruktor der Klasse aufrufen, und dann den EINEN verdammten Eintrag zurückgeben.
Wir haben diese Zeile dann durch das gute alte Mage::getModel(‘sales/quote’)->load($id) ersetzt und konnten so die Performance um den Faktor 50.000 erhöhen;)
Ich frage mich was die Idee hinter dieser Methode ist und warum eine dermaßen nicht skalierende Methode überhaupt im Magento-Core vorhanden ist. Oder gibt es da vernünftige Einsatzbereiche?