mass deleting wordpress-posts with SQL

ich hatte ein kaputtes wordpress-plugin, welches mir einen rss-feed mehrfach als artikel importiert hat. also jedes einzelne item des feeds wurde 5-20 mal importiert.
das führte zu ca. 90.000 unerwünschten artikeln in der datenbank.

leider legt wordpress zusätzlich zum artikel noch einige verknüpfte datensätze in weiteren tabellen an. das sind verschiedene meta-informationen und datenfelder. diese tabellen wurden durch den fehlerhaften import ebenso voll gemüllt.

zum glück habe ich bei der konfiguration mitgedacht und einen speziellen user angelegt, unter dessen post_author id ausschließlich rss-artikel importiert wurden.

somit war es möglich eine klare abgrenzung zu machen und über die sql-console ein sql-statement zu formulieren das alle posts eines authors und die mit ihnen verknüpften daten löscht.

die abgrenzung sollte auch über eine bestimmte kategorie oder spezifische tags funktionieren indem man die where-klausel am ende der jeweiligen statements anpasst.

zum prüfen ob der selektor funktioniert, empfehle ich erstmal eine SELECT-abfrage zu machen:

SELECT *
FROM wp_posts
LEFT JOIN wp_term_relationships ON ( wp_posts.ID = wp_term_relationships.object_id )
LEFT JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id )
LEFT JOIN wp_term_taxonomy ON ( wp_term_taxonomy.term_taxonomy_id = wp_term_relationships.term_taxonomy_id )
LEFT JOIN wp_terms ON ( wp_terms.term_id = wp_term_taxonomy.term_id )
WHERE wp_posts.post_author=X

um die löschung auszuführen wird die erste zeile – der select – mit delete und den tabellen ersetzt in denen gelöscht werden soll.

DELETE wp_posts, wp_term_relationships, wp_postmeta, wp_term_taxonomy
FROM wp_posts
LEFT JOIN wp_term_relationships ON ( wp_posts.ID = wp_term_relationships.object_id )
LEFT JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id )
LEFT JOIN wp_term_taxonomy ON ( wp_term_taxonomy.term_taxonomy_id = wp_term_relationships.term_taxonomy_id )
LEFT JOIN wp_terms ON ( wp_terms.term_id = wp_term_taxonomy.term_id )
WHERE wp_posts.post_author=X

auf einer lokalen test-datenbank hat die löschabfrage nur einige sekunden gedauert und etwa 200mb speicherplatz freigegeben. auf meinem shared host hat die löschabfrage über drei minuten gedauert.
falls die maximale script-laufzeit die ausführung unterbricht, kann das delete statement erneut gestartet werden. nach dem erfolgreichen löschen sollte beim erneuten ausführen der select-abfrage kein ergebnis mehr angezeigt werden.

(via: https://codex.wordpress.org/Database_Description#Database_Diagram; https://wpguru.co.uk/2013/02/how-to-bulk-delete-posts-in-wordpress-with-mysql/)