Rendimiento y monitorización

Consultas SQL para limpiar datos huérfanos y purgar la base de datos de WordPress

Revisado el · wordpress · base de datos · rendimiento

En instalaciones de WordPress que llevan en activo muchos años, o que han tenido mucha actividad (contenidos, cambios, actualizaciones, plugins) pueden llevar a situaciones que requieran depurar y limpiar contenidos no necesarios de la base de datos, principalemente contenido denominado "huérfano", filas de la base de datos que no están en uso, pero que por error siguen presentes.

Estas acciones de limpieza se pueden llevar a cabo por medio de consultas SQL que nos ayudarán a automatizar las tareas, estas consultas se pueden ejecutar de forma sencilla desde el apartado SQL de la herramienta phpMyAdmin, disponible en cPanel.

Recuerda que en todos los ejemplos las tablas usarán el prefijo wp_, si tu instalación de WordPress usa otro prefijo diferente, deberás cambiar las consultas para que así lo reflejen, cambiando donde aparezca wp_ por el que corresponda en tu caso.

Advertencia: no ejecutes un DELETE directamente en producción. Haz primero la limpieza en un clon, valida la web y conserva una copia recuperable de la base original.

Preparación obligatoria

Pon la web en mantenimiento para evitar escrituras y exporta la base con WP-CLI:

umask 077
wp db export wp-antes-limpieza.sql
sha256sum wp-antes-limpieza.sql > wp-antes-limpieza.sql.sha256
chmod 400 wp-antes-limpieza.sql wp-antes-limpieza.sql.sha256
sha256sum -c wp-antes-limpieza.sql.sha256

Descarga la copia y verifica una restauración en una base temporal. Ejecuta primero cada SELECT COUNT(*), revisa después una muestra con SELECT ... LIMIT 50 y solo entonces adapta el DELETE correspondiente.

En tablas InnoDB puedes agrupar una limpieza revisada dentro de una transacción:

START TRANSACTION;
-- Ejecuta aquí un único DELETE ya revisado.
-- Repite el SELECT de control antes de confirmar.
ROLLBACK;

Usa ROLLBACK durante el ensayo. Sustitúyelo por COMMIT solo cuando el recuento y la muestra sean correctos. Las tablas MyISAM no permiten revertir una transacción; conviértelas o trabaja exclusivamente sobre el clon y recupera desde la copia si falla.

Eliminar etiquetas que no están en uso

No borres directamente en wp_terms, wp_term_taxonomy o wp_term_relationships: WordPress mantiene relaciones y cachés mediante sus APIs. Lista primero las etiquetas vacías:

wp term list post_tag --hide_empty --fields=term_id,name,count

Revisa los identificadores en staging y elimina únicamente los aprobados, uno a uno o en lotes pequeños, mediante WP-CLI:

wp term delete post_tag ID_REVISADO

Valida después entradas, categorías, etiquetas y enlaces permanentes. Si algo no coincide, restaura la base exportada.

Eliminar wp_postmeta que no disponga de posts (wp_posts) asociados

SELECT COUNT(*) AS filas_afectadas
FROM wp_postmeta pm
LEFT JOIN wp_posts p ON pm.post_id = p.ID
WHERE p.ID IS NULL;

SELECT pm.*
FROM wp_postmeta pm
LEFT JOIN wp_posts p ON pm.post_id = p.ID
WHERE p.ID IS NULL
LIMIT 50;

DELETE wp_postmeta FROM wp_postmeta
LEFT JOIN wp_posts ON (wp_postmeta.post_id = wp_posts.ID)
WHERE (wp_posts.ID IS NULL);

Eliminar wp_usermeta que no disponga de usuarios (wp_users) asociados

SELECT COUNT(*) AS filas_afectadas
FROM wp_usermeta um
LEFT JOIN wp_users u ON um.user_id = u.ID
WHERE u.ID IS NULL;

SELECT um.*
FROM wp_usermeta um
LEFT JOIN wp_users u ON um.user_id = u.ID
WHERE u.ID IS NULL
LIMIT 50;

DELETE wp_usermeta FROM wp_usermeta
LEFT JOIN wp_users ON (wp_usermeta.user_id = wp_users.ID)
WHERE (wp_users.ID IS NULL);

Reasignar posts cuyo usuario ya no exista

No elimines esos posts: reasígnalos a un administrador válido. Obtén primero su ID con wp user list, cuenta y revisa los contenidos afectados:

SELECT COUNT(*) AS posts_huerfanos
FROM wp_posts p
LEFT JOIN wp_users u ON p.post_author = u.ID
WHERE u.ID IS NULL;

SELECT p.ID, p.post_type, p.post_status, p.post_title, p.post_author
FROM wp_posts p
LEFT JOIN wp_users u ON p.post_author = u.ID
WHERE u.ID IS NULL
LIMIT 50;

UPDATE wp_posts p
LEFT JOIN wp_users u ON p.post_author = u.ID
SET p.post_author = ID_ADMIN_VALIDO
WHERE u.ID IS NULL;

Eliminar todas las revisiones de los posts

En este ejemplo se seleccionan revisiones con más de 10 días. Confirma el recuento y la muestra antes de eliminar:

SELECT COUNT(*) AS revisiones_afectadas
FROM wp_posts
WHERE post_type = 'revision'
  AND post_modified_gmt < DATE_SUB(NOW(), INTERVAL 10 DAY);

SELECT ID, post_parent, post_modified_gmt
FROM wp_posts
WHERE post_type = 'revision'
  AND post_modified_gmt < DATE_SUB(NOW(), INTERVAL 10 DAY)
LIMIT 50;

DELETE FROM wp_posts
WHERE post_type = 'revision'
  AND post_modified_gmt < DATE_SUB(NOW(), INTERVAL 10 DAY);

Eliminar los datos transients de la tabla wp_options

Los transients son datos temporales que WordPress y los plugins gestionan mediante su API. Previsualiza primero los expirados:

wp transient list --fields=name,expiration

Después de validar el clon y la copia, elimina únicamente los expirados mediante la API:

wp transient delete --expired

Al terminar, comprueba el frontal, el administrador, las tareas programadas y los registros de error. Conserva el export hasta terminar el periodo de observación; para revertir, detén las escrituras y restaura la copia verificada.

También te puede ayudar

  1. Consultas SQL lentas de tipo "SELECT SQL_CALC_FOUND_ROWS"
  2. Lentitud de rendimiento consultas SQL usando LEFT JOIN
  3. Mejora del rendimiento de la base de datos de WordPress con Index WP MySQL For Speed
  4. Optimizar la tabla wp_options y los datos de tipo "autoload"