投稿・ユーザー・カスタムフィールド・タグのゴミデータをDBから自動削除する方法
こんにちは、webエンジニアのゾノ( @ozonosho )です。
さて、今回の記事ではWordPressで投稿・ユーザー・カスタムフィールド・タグのゴミデータをDBから自動削除する方法を紹介したいと思います。
WordPressは管理画面から記事削除やユーザー削除ができます。
しかしながら削除操作をした際にデータも綺麗にすべて消えるのかというと、実は消えないんですよね。ゴミデータが残ります。
たとえばユーザーを削除した場合、そのユーザーの投稿記事はサイト上からは消えますが、DB内にはなぜかリビジョンデータとして残ります。同様に、削除されたユーザーの投稿記事に紐づくカスタムフィールドもDB内にデータが残ります。
(なぜ!?笑)
サイトによっては1つの投稿にたいして10以上のカスタムフィールドを利用しているケースもあるため、数万件の投稿を扱うサイト規模になると不要なゴミデータが表示速度に大きな影響を及ぼしてきます。
実際の例として、僕の運営する相談サイト『ココトモ』では過去に利用していた掲示板プラグインが多数のカスタムフィールドを生成しており、不要なゴミデータ(wp_postmetaのデータ)が30万件ほど溜まっていましたw
そんなわけで今回、1日1回DB内の不要なゴミデータを一括削除する自動処理を作ってみました。
1日1回DB内の不要なゴミデータを一括削除する自動処理
下記のコードをfunctions.phpに追加してあげればOKです。
//①ゴミデータ削除
function clean_db() {
global $wpdb;
//削除済ユーザーが投稿者になっているwp_postmetaデータ削除
$query = $wpdb->prepare("DELETE t1 FROM wp_postmeta t1 WHERE t1.post_id in (SELECT t2.ID FROM wp_posts t2 LEFT JOIN wp_users t3 ON t2.post_author = t3.ID WHERE t3.ID IS NULL)");
$wpdb->query($query);
//削除済ユーザーが投稿者になっているwp_postsデータ削除
$query = $wpdb->prepare("DELETE t1 FROM wp_posts t1 LEFT JOIN wp_users t2 ON t1.post_author = t2.ID WHERE t2.ID IS NULL");
$wpdb->query($query);
//リビジョンデータを削除(これで管理者に引き継がれた削除済ユーザーの投稿データも消える)
$query = $wpdb->prepare("DELETE FROM wp_posts WHERE post_type = 'revision'");
$wpdb->query($query);
//利用されていないタグ・カテゴリー・タームの削除
$query = $wpdb->prepare("DELETE t1 FROM wp_terms t1 LEFT JOIN wp_term_taxonomy t2 ON t1.term_id = t2.term_id WHERE t2.count = 0");
$wpdb->query($query);
$query = $wpdb->prepare("DELETE FROM wp_term_taxonomy WHERE NOT EXISTS (SELECT 'x' FROM wp_terms WHERE wp_terms.term_id = wp_term_taxonomy.term_id)");
$wpdb->query($query);
$query = $wpdb->prepare("DELETE FROM wp_term_relationships WHERE NOT EXISTS (SELECT 'x' FROM wp_term_taxonomy WHERE wp_term_taxonomy.term_taxonomy_id = wp_term_relationships.term_taxonomy_id)");
$wpdb->query($query);
//wp_postsが無いwp_postmetaを削除
$query = $wpdb->prepare("DELETE FROM wp_postmeta WHERE NOT EXISTS (SELECT 'x' FROM wp_posts WHERE wp_posts.ID = wp_postmeta.post_id)");
$wpdb->query($query);
//wp_usersが無いwp_usermetaを削除
$query = $wpdb->prepare("DELETE FROM wp_usermeta WHERE NOT EXISTS (SELECT 'x' FROM wp_users WHERE wp_users.ID = wp_usermeta.user_id)");
$wpdb->query($query);
}
add_action('clon_clean_db', 'clean_db');
//②実装した処理を日毎に実行
if(!wp_next_scheduled('clon_clean_db')) {
wp_schedule_event(time() + 10, 'daily', 'clon_clean_db' );
}
①の中の各処理で不要なゴミデータを削除しています。
もし、削除したユーザーの投稿も残しておく必要がある場合(例:削除したユーザーの投稿記事をサイト内に表示しておきたい)は、先頭2つの処理を外してください。
あるいは、固定ページなどは投稿したユーザーを削除しても残し、記事のデータだけ投稿ユーザーを削除した場合に一緒に削除したい場合は、先頭2つの処理を下記に置き換えてください。
//削除済ユーザーが投稿者になっているwp_postmetaデータ削除(投稿タイプpostに該当するデータのみ)
$query = $wpdb->prepare("DELETE t1 FROM wp_postmeta t1 WHERE t1.post_id in (SELECT t2.ID FROM wp_posts t2 LEFT JOIN wp_users t3 ON t2.post_author = t3.ID WHERE t3.ID IS NULL AND t2.post_type='post')");
$wpdb->query($query);
//削除済ユーザーが投稿者になっているwp_postsデータ削除(投稿タイプpostに該当するデータのみ)
$query = $wpdb->prepare("DELETE t1 FROM wp_posts t1 LEFT JOIN wp_users t2 ON t1.post_author = t2.ID WHERE t2.ID IS NULL AND t1.post_type='post'");
$wpdb->query($query);
リビジョンデータを残したい場合は先頭から3つ目の処理は外してください。
作成した①の関数をWordPressのcronを利用して定期実行させれば自動処理化できます。
今回は1日1回実行させるようにしたので②のコードを記述しました。
「1日1回」であれば元々WordPress側が「daily」というスケジュールを用意してくれているのでそれを利用するだけで登録できます。
おわりに
以上、今回の記事では WordPressで投稿・ユーザー・カスタムフィールド・タグのゴミデータをDBから自動削除する方法 を紹介させていただきました。
当サイトではWordPressのカスタマイズ依頼を請け負っています。実現したい機能・要望がある方はぜひ下記ページよりご相談ください。