2022.01.23

投稿・ユーザー・カスタムフィールド・タグのゴミデータを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のカスタマイズ依頼を請け負っています。実現したい機能・要望がある方はぜひ下記ページよりご相談ください。

あなたのサイトに理想の機能を実装!WordPressカスタマイズサービス

本サービスはあなたのWordPressサイトに理想の機能を実装するサービスとなります。 どのような機能・要望でも実現可能です! Wo......

→この記事を読む