私は挿入したいcsvファイルを持っています。それは〜1,500行と97列で構成されています。フルインポートを行うのに約2〜3時間かかります。方法がある場合はこれを改善したいと思います。現在、各行に対して$ post_id = wp_insert_postを実行してから、各行に関連付けられた97列に対してadd_post_metaを実行しています。これはかなり非効率的です...
Aがpost_idにpostとそのpost_metaの値の関係を保つことができるような方法でこれについて取り組むより良い方法はありますか?
今、私はwampで私のローカルマシンでこれを試していますが、VPSでそれを走らせるでしょう
私はカスタムCSVインポートに関しても同様の問題を以前に抱えていましたが、一括挿入にカスタムSQLを使用することになりました。しかし、私はそれまでにこの答えを見ていませんでした:
用語のカウントを有効または無効にするには、 wp_defer_term_counting()
を使用します。
また、WordPressインポータープラグインの source )をチェックアウトすると、一括インポートの直前にこれらの関数が表示されます。
wp_defer_term_counting( true );
wp_defer_comment_counting( true );
そして、一括挿入の後:
wp_defer_term_counting( false );
wp_defer_comment_counting( false );
だからこれは試してみることになるかもしれません;-)
publishの代わりにドラフトとして投稿をインポートすると、それぞれに固有のスラッグを見つけるという遅いプロセスがスキップされるため、作業がスピードアップします。例えば、後で小さなステップでそれらを公開しますが、この種のアプローチではインポートされた投稿に何らかの形でマークを付ける必要があるので、後でドラフトを公開するだけではありません。これは慎重な計画とたぶんカスタムコーディングを必要とするでしょう。
もしあれば似たような投稿タイトル(同じpost_name
)をたくさんインポートすると、利用可能なスラッグを見つけるためのループクエリの繰り返しのためにwp_unique_post_slug()
が遅くなる可能性があります。これにより、膨大な数のdbクエリが生成される可能性があります。
WordPress 5.1以降、スラッグのループ反復を避けるためにpre_wp_unique_post_slug
フィルタが利用可能です。コアチケット #21112 を参照)これは例です:
add_filter( 'pre_wp_unique_post_slug',
function( $override_slug, $slug, $post_id, $post_status, $post_type, $post_parent ) {
// Set a unique slug value to shortcircuit the slug iteration loop.
// $override_slug = ...
return $override_slug;
}, 10, 6
);
例えば試してみると$suffix
を$post_id
として$override_slug = _truncate_post_slug( $slug, 200 - ( strlen( $suffix ) + 1 ) ) . "-$suffix"
とすると、期待通り、新しい投稿では$post_id
は常に0
であることに気付くでしょう。 uniqid( '', true )
のように、PHPでユニークな数を生成するにはさまざまな方法があります。しかし、あなたがユニークなナメクジを持っていることを確認するために慎重にこのフィルターを使用してください。例えば後でpost_name
に対してグループカウントクエリを実行してください。
タイムアウトを回避するには WP-CLI を使用します。例えば、 .csvファイルを使用して20,000の投稿またはページを作成しますか? について投稿された回答を参照してください。
それから、WP-CLIコマンドでカスタムPHPインポートスクリプトimport.php
を実行します。
wp eval-file import.php
現在のwp-admin UIではうまく処理できないため、大量の階層型投稿タイプのインポートも避けてください。例えば参照。 カスタム投稿タイプ - 投稿リスト - 死の白い画面
これが@ottoからの素晴らしいヒントです:
一括挿入の前に、明示的にautocommit
モードを無効にします。
$wpdb->query( 'SET autocommit = 0;' );
一括挿入後、次のコマンドを実行してください。
$wpdb->query( 'COMMIT;' );
私はまた、ハウスキーピングを次のようにするのが得策だと思います。
$wpdb->query( 'SET autocommit = 1;' );
これをMyISAMでテストしたことはありませんが、これはInnoDBで動作するはずです。
@kovsheninによる による)このヒントはMyISAMではうまくいきません。
IDを取得するには投稿を挿入する必要がありますが、$wpdb->postmeta
テーブルの構造は非常に単純です。おそらく、INSERT INTO
ステートメント MySQLのドキュメントにあるように、INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);
のように)を使用することができます。
あなたの場合は….
$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}");
これは、エンコーディング、シリアライゼーション、エスケープ、エラーチェック、複製、その他には関係ありませんが、もっと速くなることを期待しています(試したことはありませんが)。
私は本番サイトで徹底的なテストなしにこれをしないでしょう、そして私が一度か二度だけそれをしなければならなかったならば、私は物事が輸入する間、私はコア機能を使い、長い昼食をとるでしょう。
私はこれを追加しなければなりませんでした:
remove_action('do_pings', 'do_all_pings', 10, 1);
これはdo_all_pings
をスキップすることに注意してください。これはpingback、エンクロージャ、trackback、そして他のpingを処理します(link: https://developer.wordpress.org/reference/functions/do_all_pings/ )。コードを見て私が理解しているのは、このremove_action
行を削除しても、保留中のpingback/trackback/enclosuresは処理されるということですが、完全にはわかりません。
更新日:私も追加しました
define( 'WP_IMPORTING', true );
私が使っていることを超えて:
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
(i.e. 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 );
'SET autocommit = 0;'
に関する重要な注意スクリプトが実行を停止した場合(何らかの理由でexit
、致命的なエラーなど)にautocommit = 0
を設定した後は、変更はDBに保存されません。
$wpdb->query( 'SET autocommit = 0;' );
update_option("something", "value");
exit; //lets say, here happens error or anything...
$wpdb->query( 'COMMIT;' );
この場合update_option
はDBに保存されません!
そのため、万が一のためにCOMMIT
をshutdown
関数に登録することをお勧めします(予期しない終了が発生した場合)。
register_shutdown_function( function(){
$GLOBALS['wpdb']->query( 'COMMIT;' );
} );