J'ai beaucoup de mal avec l'inefficacité de node_save (). Mais le nœud sauve-t-il mon problème? C'est finalement ce que j'essaie de découvrir.
J'ai créé une boucle avec 100 000 itérations. J'ai créé le strict minimum pour que l'objet nœud soit valide et enregistre correctement. Voici le code de sauvegarde du nœud:
$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);
}
Voici les résultats:
100 000 nœuds ont été enregistrés, chacun utilisant node_save (). Il a fallu 5196,22 secondes pour terminer. C'est SEULEMENT 19 sauve une seconde.
Pour dire le moins, ce n'est pas acceptable, surtout lorsque cette personne reçoit environ 1 200 requêtes d'insertion individuelles par seconde , et que cette personne reçoit 25 000 insertions par seconde .
Alors, que se passe-t-il ici? Où est le goulot d'étranglement? Est-ce la fonction avec la fonction node_save () et comment est-elle conçue?
Serait-ce mon matériel? Mon matériel est un serveur de développement, personne d'autre que moi - Intel dual core, 3Ghz, Ubuntu 12.04 avec 16 Go de RAM.
Pendant que la boucle fonctionne, mon utilisation des ressources est: MySQL 27% CPU, 6M RAM; PHP 22% CPU 2M RAM.
Ma configuration mysql a été effectuée par l' assistant percona .
Mysql dit que si mon utilisation CPU est inférieure à 70%, mon problème est lié au disque . Certes, je n'ai qu'une course du moulin WD Caviar 7200 RPM, mais je devrais obtenir plus de 19 insertions par seconde avec lui, j'espère!
Il n'y a pas si longtemps, j'ai écrit sur la sauvegarde de 30 000 nœuds par jour . Cependant, pour être clair, ce nœud n'a rien à voir avec des forces externes. C'est purement une référence pour savoir comment augmenter la vitesse des appels à node_save ().
De manière réaliste, j'ai besoin d'obtenir 30 000 éléments dans la base de données chaque minute en utilisant node_save. Si la sauvegarde de nœud n'est pas une option, je me demande si je peux écrire ma propre fonction drupal api "node_batch_save ()" ou quelque chose qui tire parti de la capacité de mysql à faire des insertions en masse avec la requête INSERT . Réflexions sur la façon d'aborder cela?
la source
Réponses:
Vous n'obtiendrez jamais 30 000 insertions par minute en utilisant node_save. En aucune façon.
Un INSERT est rapide car c'est tout ce qu'il fait. L'enregistrement de nœud effectue plusieurs insertions (table principale, table de révision, une table pour chaque champ), efface tous les caches d'entités et déclenche les crochets. Les crochets sont la partie délicate. Si vous avez de nombreux modules contrib (ou même un qui se comporte mal) qui peuvent vraiment nuire aux performances, surtout si l'auteur n'a pas tenu compte du cas d'utilisation "Je sauvegarde une tonne de nœuds à la fois". Par exemple, j'ai dû ajouter ceci à ma classe Migrate:
D'un autre côté, si vous écrivez une fonction de sauvegarde personnalisée qui n'invoque aucun hook, vous courez un risque évident d'obtenir des données incohérentes, dans un état inattendu par le système. Je ne recommanderais jamais de faire ça. Lancez xhprof et voyez ce qui se passe.
la source
node_save()
, mais ajoute un peu de code pour atténuer les problèmes connus qui peuvent être causés, comme Pathauto la reconstruction du cache de menu après chaque noeud de sauvegardeTout d'abord, installez XCache / APC (pour PHP <5.5) et configurez memcached pour Drupal.
Ensuite, vous pouvez optimiser votre configuration MySQL pour les requêtes lourdes en utilisant le script mysqltuner disponible sur: http://mysqltuner.pl
Par exemple
Autres suggestions:
la source
Utilisez le module Mongodb pour stocker les champs https://drupal.org/project/mongodb Résultats ici: selon http://cyrve.com/mongodb
la source