Als Beispiel kann man die Artikel auf der Startseite nennen, diese sind oft die gleichen und können daher aus dem Cache geladen werden.
Ebenfalls sollten FlatTables aktiviert werden und die Rewrite-URLs erstellen lassen ohne Kategorie Pfad.
Key-Facts
- 1. Magento 1.8.0.0, vorher 1.7.0.2
- 2. 1.5 Mio Artikel insgesamt
- 3. 50.000 Artikel Änderungen pro Tag
Nun zum eigentlichen Problem
Wir standen vor der Aufgabe einen Shop auf Basis von Magento zu erstellen mit einem Artikelstamm von 1.5 Mio. Artikeln, hinzukommen aber ca. 50.000 Artikel Updates pro Tag.
Als Import-Basis hatte sich meine Kollege Volker Thiel dazu entschieden das Modul AvS_FastSimpleImport zu verwendet, welches auf Mage_ImportExport aufbaut.
Das Parsen der Daten (XML) des ERP vom Kunden dauert im Schnitt 30 Minuten, der Import ohne Indexing dauert ca. 10 Minuten.
Wie die meisten schon vermuten, lag das Hauptproblem beim Indexer. Dieser lief jeden Tag
mehr als 6 Stunden und hat dazu geführt, dass Kunden im Shop nicht kaufen konnten („Lock wait timeout exceeded; try restarting transaction“).
Die Lösung dazu wurde im Issue-Tracker diskutiert und direkt über das Indexer Module gelöst. [3]
Durch diese Änderung läuft der Indexer nun maximal 1 Stunde (ab 3 Uhr), da der Shop auf den deutschen Markt ausgelegt ist, stellt dieses kein Problem da.
Nachdem die Probleme mit dem Indexer behoben wurden standen wir vor dem Problem, dass die Seiten beim ersten Aufruf ca. 10 Minuten gebraucht hat. Schnell ließ sich hier durch die Datenbank herausfinden, dass das Problem an der Navigation von Magento lag („MySQL: SHOW PROCESSLIST“). In einem Query für die Kategorien wird ein JOIN auf die REWRITE Tabelle gemacht (die core_url_rewrite-Tabelle enthält ca. 1.4 Mio Zeilen). Dadurch, dass in der Nacht immer Änderungen vorgenommen werden, musste der Index neu aufgebaut werden. Allerdings ist ein wichtiger Index ab Magento Version 1.5 nicht mehr enthalten ('category_id', 'is_system', 'product_id', 'store_id', 'id_path' ). Dieser Index brachte zwar eine deutliche Verbesserung, aber immer noch in einem inakzeptablen-Bereich ~3 Minuten.
Meine Lösung ist hierfür realtiv simple, es werden die Einträge der Kategorie URL-Rewrites in eine andere Tabelle kopiert und im JOIN statt auf die core_url_rewrite Tabelle auf meine neue Tabelle zugegriffen (Referenz: Mage_Catalog_Helper_Category_Url_Rewrite). Die Aufrufe liegen jetzt in einem so kleinen Bereich auf diese Tabelle, abfrage, dass selbst wenn die Daten nicht auf dem Cache kommen direkt geliefert werden.
Hier zu habe ich ein Modul geschrieben welches ebenfalls, die Kategorie Pfade für Artikel nicht mit Indexiert [3].
Zum Caching, anfangs hatten wir auch auf Redis [4] gesetzt, später und nach einigen Tests sind wir umgestiegen auf MongoDB [5] als Cache. Hier stißen wir auch auf ein kleines Problem, dass die veralteten Cache Daten nicht direkt gelöscht wurden. Dafür haben ich ein kleines Script geschrieben, welches dieses übernimmt.[6]
Zum Server
Es handelt sich um einen Dedicated Server mit Debian Wheezy amd64.
Als Webserver verwenden wir nginx und php-fpm.
PHP in der Version 5.3.27.
Als Opcache nutzen wir statt APC, Zend Opcache (ehemals ZendOptimizer+) [7].
Dieser war in unserem Test deutlich schneller als APC, wenn man trotzdem APC UserCache benötigt kann man sich APCu [8] anschauen.
Das MemoryLimit liegt default bei 128 M, im Checkout auf 512 M und im Backend bei 756 M.
Dieses sind jeweils eigene Prozessbereiche über PHP-FPM.
Als MySQL Server wurde MariaDB 5.5 verwendet.
Dedicated Server Hardware:
- Hexacore mit Hyper-Threading – 3,2 GHz
- 2x 2 Terabyte SW-RAID1
- 64 GB ECC-RAM