Vom: 14.03.2013

Objekte erzeugen in Pimcore beschleunigen

Wer in Pimcore schon in der Situation war, viele User-Objekte erzeugen zu müssen (zum Beispiel bei Datenabgleichen mit anderen System) wird festgestellt haben, dass dies eher gemächlich vonstatten geht. Mit zwei einfachen Maßnahmen kann man dem Prozess gehörig auf die Sprünge helfen.

Den Cache aktivieren

Ist in Pimcore kein Cache konfiguriert, wird per Default der Zend_File_Cache verwendet. Das ist zwar besser wie nichts, aber immer noch sehr langsam. Der Cache wird nur dann deaktiviert, wenn man dies explizit mit

Pimcore_Model_Cache::disable();

so setzt. Es empfiehlt sich daher, den Cache auf eine schnelle Variante wie Memcached oder die MongoDB zu konfigurieren.

Memcache

Memcache ist ultraschnell, da er ausschliesslich im Speicher läuft, hat aber einen Nachteil - alles, was da reingestopft wird, ist global für jeden mit Zugriff auf den Daemon verfügbar. Um hier abgrenzen zu können, setzt Pimcore eine Zwischenschicht zum Taggen ein, und jene Tags werden wiederum in der normalen SQL-Datenbank abgelegt - dieser Umstand macht also den Memcache für Pimcore nicht zu ersten Wahl.

MongoDB

Die MongoDB ist die schnellere Alternative zum Memcache – obwohl sie im Prinzip eigentlich die langsamere wäre, es fehlt aber das Tagging-Handicap. Die Installation der Datenbank sollte einfach zu bewerkstelligen sein, die meisten Distributionen enthalten sie. Die Konfiguration in Pimcore erfolgt über die Datei website/var/config/cache.xml. Eine Beispiel-Datei existiert schon in dem Verzeichnis. Eine funktionierende Version der cache.xml für die MongoDB würde Beispielsweise so aussehen:

    
    
        Core
        
            pricelist_
            99999
            true
        
    
    
        Pimcore_Cache_Backend_Mongodb
        true
        
            pimcore_cache
        
    

Die Datei wird bei jedem Request an Pimcore gesucht, sobald sie vorhanden ist, ist der Cache aktiv.

Den Cache nutzen um Zend_Db_Table zu beschleunigen

Beim Anlegen von vielen Objekten zeigt sich eine kleine, ich will nicht sagen, Unzulänglichkeit, von Zend_Db_Table: Standardmäßig fragt Zend_Db_Table_Abstract die darunterliegende Datenbank für die Metadaten der Tabelle ab immer wenn diese diese Daten benötigt werden um Tabellenoperationen durchzuführen. Das Tableobjekt holt die Metadaten der Tabelle von der Datenbank indem es die describeTable() Methode des Adapters verwendet. [...] In einigen Fällen, speziell wenn viele Table Objekte auf der gleichen Datenbanktabelle instanziert werden kann das Abfragen der Datenbank nach den Metadaten der Tabelle für jede Instanz unerwünscht sein wegen der Geschwindigkeit. In solchen Fällen, können Benutzer davon profitieren das die Metadaten der Tabelle, die von der Datenbank empfangen werden, gecached werden. Die Kurzfassung: bei jedem Erzeugen eines Daten-Objekts wird die Datenbank gefragt, wie die Daten denn auszusehen haben. Dieser Vorgang kostet enorm viel Zeit und kann gecached werden mit Zend_Db_Table_Abstract::setDefaultMetadataCache() Dieser statischen Methode muss einfach nur ein Cache übergeben werden – und einen solchen stellt Pimcore, wie weiter oben beschrieben, zur Verfügung. Folgende beiden Zeilen aktivieren daher den Metadaten-Cache für Zend_Db_Table:

$cache = Pimcore_Model_Cache::getInstance();
Zend_Db_Table_Abstract::setDefaultMetadataCache($cache);

Die Praxis

Bei einem Kunden war es notwendig, ca 3500 Objekte (mit Assets, es finden also auch Kopiervorgänge auf der Platte statt) zu importieren. Ohne Cache dauerte dies ca 2 Stunden, mit Cache 15 Minuten, und mit dem Metadaten-Cache nur noch fünf Minuten. In der Praxis haben diese beiden Maßnahmen uns also enorme Geschwindigkeitssteigerungen gebracht! EDIT: Wir haben diese Verbesserung als Issue bei Elements eingereicht: Activate caching Zend table metadata by default. Die zwei Zeilen sind angemommen worden, ab Version 1.4.10 ist der Cache daher nun im Core von vornherein mit drin :)