Ich habe große Probleme mit der Ineffizienz von node_save (). Aber ist Node Save mein Problem? Das versuche ich letztendlich herauszufinden.
Ich habe eine Schleife mit 100.000 Iterationen erstellt. Ich habe das absolute Minimum für das Knotenobjekt erstellt, damit es gültig ist und korrekt gespeichert wird. Hier ist der Knotenspeichercode:
$node = new stdClass();
$node->type = "test_page";
node_object_prepare($node);
$node->uid = 1;
$node->title = $node_title;
$node->status = 1;
$node->language = LANGUAGE_NONE;
if($node = node_submit($node)){
node_save($node);
}
Hier sind die Ergebnisse:
100.000 Knoten wurden jeweils mit node_save () gespeichert. Die Fertigstellung dauerte 5196,22 Sekunden. Das sind NUR 19 spart eine Sekunde.
Zumindest ist dies nicht akzeptabel, insbesondere wenn diese Person ungefähr 1200 einzelne Einfügeabfragen pro Sekunde erhält und diese Person 25.000 Einfügungen pro Sekunde erhält .
Also, was ist hier los? Wo ist der Engpass? Ist es die mit der Funktion node_save () und wie ist sie aufgebaut?
Könnte es meine Hardware sein? Meine Hardware ist ein Entwicklungsserver, niemand außer mir - Intel Dual Core, 3 GHz, Ubuntu 12.04 mit 16 GB RAM.
Während die Schleife ausgeführt wird, ist meine Ressourcennutzung: MySQL 27% CPU, 6 MB RAM; PHP 22% CPU 2M RAM.
Meine MySQL-Konfiguration wurde vom Percona-Assistenten durchgeführt .
MySQL sagt, dass mein Problem festplattengebunden ist , wenn meine CPU-Auslastung unter 70% liegt . Zugegeben, ich habe nur eine WD Caviar 7200 U / min, aber ich hoffe, ich sollte mehr als 19 Einsätze pro Sekunde damit bekommen!
Vor nicht allzu langer Zeit habe ich über das Speichern von 30.000 Knoten an einem Tag geschrieben . Um klar zu sein, hat dieser Knoten jedoch nichts mit externen Kräften zu tun. Es ist lediglich ein Benchmark, um zu erfahren, wie Sie die Geschwindigkeit von Aufrufen von node_save () erhöhen können.
Realistisch gesehen muss ich mit node_save jede Minute 30.000 Elemente in die Datenbank aufnehmen. Wenn das Speichern von Knoten keine Option ist, frage ich mich, ob ich meine eigene Drupal-API-Funktion "node_batch_save ()" schreiben kann oder etwas, das die Fähigkeit von mysql nutzt, Masseneinfügungen mit der INSERT-Abfrage durchzuführen . Gedanken darüber, wie man das angeht?
quelle
Antworten:
Mit node_save erhalten Sie niemals 30.000 Einfügungen pro Minute. Auf keinen Fall.
Ein INSERT ist schnell, weil das alles ist, was es tut. Das Speichern von Knoten führt mehrere Einfügungen durch (Haupttabelle, Revisionstabelle, eine Tabelle für jedes Feld), löscht alle Entitätscaches und löst Hooks aus. Die Haken sind der schwierige Teil. Wenn Sie viele Contrib-Module haben (oder sogar eines, das sich schlecht verhält), die die Leistung wirklich beeinträchtigen können, insbesondere wenn der Autor den Anwendungsfall "Ich speichere eine Menge Knoten auf einmal" nicht berücksichtigt hat. Zum Beispiel musste ich dies meiner Migrate-Klasse hinzufügen:
Wenn Sie dagegen eine benutzerdefinierte Speicherfunktion schreiben, die keine Hooks aufruft, besteht eindeutig die Gefahr, dass inkonsistente Daten in einem vom System unerwarteten Zustand abgerufen werden. Ich würde das niemals empfehlen. Starten Sie xhprof und sehen Sie, was passiert.
quelle
node_save()
, aber einige Code fügt bekannte Probleme zu mildern, die wie Pathauto Wiederaufbau des Menü - Cache nach jedem Knoten speichern verursacht werden könnenInstallieren Sie zunächst XCache / APC (für PHP <5.5) und konfigurieren Sie memcached für Drupal.
Anschließend können Sie Ihre MySQL-Konfiguration für umfangreiche Abfragen optimieren, indem Sie das Skript mysqltuner verwenden, das unter folgender Adresse verfügbar ist: http://mysqltuner.pl
Z.B
Weitere Vorschläge:
quelle
Verwenden Sie das Mongodb-Modul, um die Felder https://drupal.org/project/mongodb zu speichern. Ergebnisse hier: gemäß http://cyrve.com/mongodb
quelle