Schneller Weg zu wp_insert_post & add_post_meta in großen Mengen

Ich habe eine CSV-Datei, die ich einfügen möchte, die aus ~ 1.500 Zeilen und 97 Spalten besteht. Es dauert ungefähr 2-3 Stunden, um einen vollständigen Import durchzuführen, und ich möchte dies verbessern, wenn es einen Weg gibt. Zur Zeit mache ich für jede Zeile einen $ post_id = wp_insert_post und dann einen add_post_meta für die 97 zugehörigen Spalten mit jeder Zeile. Das ist ziemlich ineffizient …

Gibt es einen besseren Weg, dies so zu tun, dass eine post_id die Beziehung zwischen post und seinen post_meta Werten erhalten könnte?

Im Moment versuche ich dies auf meinem lokalen Rechner mit Wamp, werde es aber auf einem VPS laufen lassen

Solutions Collecting From Web of "Schneller Weg zu wp_insert_post & add_post_meta in großen Mengen"

Ich hatte vor einiger Zeit ähnliche Probleme mit einem benutzerdefinierten CSV-Import, aber am Ende habe ich einige benutzerdefinierte SQL für die Masseneinfügung verwendet. Aber ich hatte diese Antwort bis dahin nicht gesehen:

Optimieren Sie das Einfügen und Löschen für Massenoperationen?

Verwenden Sie wp_defer_term_counting() , um die Zählung von Begriffen zu aktivieren oder zu deaktivieren.

Auch wenn Sie die Quelle für das WordPress-Importer-Plugin auschecken, sehen Sie diese functionen kurz vor dem Massenimport:

 wp_defer_term_counting( true ); wp_defer_comment_counting( true ); 

und dann nach dem Bulk einfügen:

 wp_defer_term_counting( false ); wp_defer_comment_counting( false ); 

Das könnte also etwas ausprobieren 😉

Das Importieren von Posts als Entwurf anstelle von Veröffentlichen beschleunigt ebenfalls die Vorgänge, da der langsame process zum Finden eines eindeutigen Slugs für jeden einzelnen übersprungen wird. Man könnte sie z. B. später in kleineren Schritten veröffentlichen, aber beachten Sie, dass diese Art von Ansatz die importierten Beiträge irgendwie markieren müsste, also veröffentlichen wir keine Entwürfe später! Dies erfordert eine sorgfältige Planung und höchstwahrscheinlich eine benutzerdefinierte Codierung.

Eine andere Option wäre WP-CLI zu verwenden, um Timeout zu vermeiden. Siehe z. B. meine Antwort zum Erstellen von 20.000 Posts oder Pages mit einer .csv-Datei?

Vermeiden Sie auch den Import einer großen Anzahl von hierarchischen Post-Typen, da die aktuelle Benutzeroberfläche von wp-admin nicht gut damit umgehen kann. Siehe zB Benutzerdefinierter Beitragstyp – Beitragsliste – weißer Bildschirm des Todes

Hier ist der große Tipp von @otto:

Deaktivieren Sie den autocommit Modus vor autocommit ausdrücklich:

 $wpdb->query( 'SET autocommit = 0;' ); 

Führen Sie nach den Masseneinfügungen Folgendes aus:

 $wpdb->query( 'COMMIT;' ); 

Ich denke auch, dass es eine gute Idee wäre, einige Hauswirtschaft zu machen wie:

 $wpdb->query( 'SET autocommit = 1;' ); 

Ich habe dies nicht auf MyISAM getestet, aber das sollte auf InnoDB funktionieren.

Wie von @kovshenin erwähnt, würde dieser Tipp für MyISAM nicht funktionieren.

Sie müssen den Post einfügen, um Ihre ID zu erhalten, aber die Tabelle $wpdb->postmeta ist sehr einfach in der Struktur. Sie könnten wahrscheinlich eine gerade INSERT INTO statement verwenden, wie dies aus der MySQL-Dokumentation hervorgeht: INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);

In Ihrem Fall…

 $ID = 1; // from your wp_insert_post $values = '($ID,2,3),($ID,5,6),($ID,8,9)'; // build from your 97 columns; I'd use a loop of some kind $wpdb->query("INSERT INTO {$wpdb->postmeta} (post_id,meta_key,meta_value) VALUES {$values}"); 

Das wird sich nicht mit Codierung, Serialisierung, Entweichen, Fehlerprüfung, Duplikaten oder irgendetwas anderem befassen, aber ich würde erwarten, dass es schneller ist (obwohl ich es nicht versucht habe).

Ich würde das auf einer Produktionsstätte nicht ohne gründliche Tests tun, und wenn ich es nur ein- oder zweimal machen müsste, würde ich die corefunktionen nutzen und ein langes Mittagessen einnehmen, während die Dinge importiert werden.

Ich musste das hinzufügen:

  remove_action('do_pings', 'do_all_pings', 10, 1); 

Denken Sie daran, dass dies do_all_pings überspringt, das Pingbacks, Enclosures, Trackbacks und andere Pings verarbeitet (Link: https://developer.wordpress.org/reference/functions/do_all_pings/ ). Mein Verständnis aus dem Blick auf den Code ist, dass ausstehende Pingbacks / Trackbacks / Enclosures noch verarbeitet werden, nachdem Sie diese remove_action Zeile entfernen, aber ich bin mir nicht ganz sicher.

Update: Ich habe auch hinzugefügt

  define( 'WP_IMPORTING', true ); 

Darüber hinaus benutze ich:

  ini_set("memory_limit",-1); set_time_limit(0); ignore_user_abort(true); wp_defer_term_counting( true ); wp_defer_comment_counting( true ); $wpdb->query( 'SET autocommit = 0;' ); /* Inserting 100,000 posts at a time including assigning a taxonomy term and adding meta keys (ie a `foreach` loop with each loop containing: `wp_insert_post`, `wp_set_object_terms`, `add_post_meta`.) */ $wpdb->query( 'COMMIT;' ); wp_defer_term_counting( false ); wp_defer_comment_counting( false );