Cómo limpiar la base de datos de WordPress

Optimizar tu base de datos es importante. Es posible que no lo notes si tienes un sitio web pequeño, pero si lo has estado gestionando ya durante un tiempo o es una página web grande, probablemente verás y notarás la diferencia cuando limpies tu base de datos.

Cada entorno y configuración es diferente, por lo que no existe un «código mágico» que haga esto por ti. Pero te daré todo tipo de consejos y trucos sobre optimización para los sistemas de administración de bases de datos más popular para WordPress: MySQL y MariaDB.

¡Stop! La base de datos es el componente más importante de tu web. Es muy delicada. Es obligatorio hacer una copia de seguridad de todo tu sitio web, incluida la base de datos, antes de realizar cambios en la misma. Si no lo haces, corres el riesgo de perder datos. Así mismo, tampoco nos hacemos responsables de ningún daño que causes a tu web.

1) Limpiar tablas de plugins desinstalados

A veces, un plugin deja sus tablas en la base de datos cuando lo eliminas. Estas tablas contienen información que el plugin utiliza, por lo que si no se va a usar más en un futuro cercano, esta información debe eliminarse.

Para ello, utilizamos el plugin Plugins Garbage Collector:

1) Instala el plugin.

2) Ve a Herramientas > Limpieza de la base de datos.

3) Asegúrate de que la opción Buscar en las tablas que no son WP esté seleccionada y haz clic en Escanear base de datos.

4) Espera a que se complete el escaneo y el plugin te mostrará una lista de todas las tablas en la base de datos que ha encontrado, resaltadas en diferentes colores.

  • Verde significa que la tabla pertenece a un plugin que está activo.
  • Azul significa que la tabla pertenece a un plugin que está instalado pero desactivado.
  • Rojo significa que la tabla pertenece a un plugin que se ha desinstalado.

¡Atención! El plugin solo debe ayudarte a tomar una decisión. No confies ciegamente en sus resultados, porque no es perfecto. Por este motivo, te recomiendo que procedas de la siguiente manera.

5) Fíjate en cada una de las líneas rojas, elimina el prefijo y búscalas en Google para saber a qué plugin pertenecen. Por ejemplo, intentemos averiguar a qué plugin pertenece la tabla wp_wpr_rucss_resources

  1. Eliminamos el prefijo de la base de datos que está presente en todas las tablas. En nuestro caso, es wp_. Nos queda wpr_rucss_resources
  2. Busca en Google «wpr_rucss_resources», incluidas las comillas: https://www.google.com/search?q=%22wpr_rucss_resources%22&oq=%22wpr_rucss_resources%22&sourceid=chrome&ie=UTF-8 
  3. Descubrimos que la tabla pertenece a WP Rocket. 
  4. Hora de decidir. ¿Desinstalamos en su momento el plugin y no lo necesitaremos en el futuro? Si es así, marcamos la casilla junto al nombre de la tabla, no la otra.

Algunos consejos útiles para trabajar con este plugin.

  • Los falsos positivos son más comunes que los falsos negativos. En otras palabras, el plugin encontrará con mayor frecuencia tablas que pertenecen a un plugin pero que están marcadas como desconocidas («Unknown») que tablas que no pertenecen a ningún plugin instalado pero que están marcadas como que sí pertenecen a un plugin.
  • No elimines nada que no sepas a qué pertenece.
  • Si tienes líneas rojas junto con líneas azules/verdes que siguen el mismo patrón en el nombre (por ejemplo, wp_wpf_modules, wp_wpf_meta_values_bk, wp_wpf_meta_values…), no las elimines. Puede ser que el plugin simplemente no haya reconocido correctamente las tablas en rojo.

2) Eliminar metadatos huérfanos y duplicados

WordPress tiene una variedad de entradas que contienen información adicional sobre tu base de datos. Por ejemplo, tus usuarios tienen una dirección de correo electrónico, un sitio web, una biografía; tus publicaciones tienen un contenido, un título, un extracto; los comentarios tienen un autor, un campo de correo electrónico, etc. Esta información a veces puede estar duplicada o huérfana (no pertenecer a nada). En tales casos, estos datos simplemente no tienen valor y pueden desordenar la base de datos de WordPress. Por lo tanto, deben limpiarse para mejorar el rendimiento y obtener una base de datos ordenada.

En primer lugar, vamos a definir los términos “huérfano” y “duplicado”:

  • Metadatos huérfanos: en WordPress, esto hace referencia a datos que ya no están asociados con una publicación o página en particular, usuario, comentario, término u otro elemento. Esto puede ocurrir si el elemento en cuestión se elimina incorrectamente o si los datos se importan o exportan incorrectamente.
  • Metadatos duplicados: estos son los datos que están duplicados en la base de datos de WordPress, lo que puede generar confusión e inconsistencia en la información. Esto puede suceder, por ejemplo, cuando una publicación o página se importa o exporta incorrectamente, o cuando los datos se ingresan manualmente varias veces. En ocasiones, un complemento defectuoso que no está codificado correctamente también puede ser la causa.

Ahora veamos los tipos individuales de metadatos.

  • Metadatos de publicaciones: los metadatos de publicaciones es la información que proporcionas a tu audiencia sobre cada publicación, como la fecha de publicación, el autor, las etiquetas de publicación no utilizadas o los campos de publicación personalizados no utilizados. Los metadatos de publicaciones también pueden ser información técnica interna, como la plantilla de publicación utilizada. La tabla usada para los metadatos de publicaciones es postmeta.
  • Metadatos de usuario: los metadatos de usuario son datos asociados con una cuenta de usuario, como el nombre, la dirección de correo electrónico y la información del perfil. Los metadatos de usuario huérfanos son metadatos de usuario que ya no están asociados con una cuenta de usuario. La tabla usada para los metadatos de ususario es usermeta.
  • Metadatos de comentarios: algunos ejemplos de metadatos de comentarios en WordPress son el nombre de un comentarista, la dirección de correo electrónico, la dirección IP y la URL del sitio web. Otros metadatos pueden incluir el contenido del comentario, la fecha y hora en que se realizó el comentario y el estado del mismo (aprobado, pendiente, spam, etc.). La tabla usada para los metadatos es commentmeta.
  • Metadatos de términos: los metadatos de términos te permiten almacenar datos para términos (etiquetas, categorías u otras taxonomías personalizadas) de manera similar a los metadatos de publicación. Estos metadatos pueden incluir información como descripciones de términos, imágenes de términos y campos de términos personalizados.
  • Relación de términos: las publicaciones o páginas están asociadas con categorías y etiquetas, y esta asociación se mantiene en la tabla de base de datos term_relationships. Esto se llama relación de términos.

Eliminar metadatos huérfanos y duplicados con un plugin

Para limpiar todos estos datos, puedes usar un plugin como WP-Sweep. Simplemente instálalo, ve a Herramientas > Sweep ¡y empieza a «barrer» todos los datos que necesites!

Eliminar metadatos huérfanos y duplicados manualmente

Sin embargo, también puedes hacerlo de forma sádica manualmente. Si tienes acceso a una herramienta de administración de bases de datos como phpMyAdmin, puedes ejecutar las siguientes consultas para seleccionar los metadatos que quieras y luego eliminarlos utilizando tu método favorito, ya sea ejecutando la consulta DELETE adecuada o seleccionando las filas a eliminar con el ratón.

Recuerda reemplazar el prefijo de la base de datos de todos los nombres de las tablas la base de datos con tu prefijo de base de datos real, que podría ser diferente de wp_.

Seleccionar todos los metadatos de publicaciones huérfanos

SELECT * FROM wp_postmeta WHERE post_id NOT IN (SELECT ID FROM wp_posts);

Seleccionar todos los metadatos de usuarios huérfanos

SELECT * FROM wp_usermeta WHERE user_id NOT IN (SELECT ID FROM wp_users);

Seleccionar todos los metadatos de comentarios huérfanos

SELECT * FROM wp_commentmeta WHERE comment_id NOT IN (SELECT comment_ID FROM wp_comments);

Seleccionar todos los metadatos de términos huérfanos

SELECT * FROM wp_termmeta WHERE term_id NOT IN (SELECT term_id FROM wp_terms);

Seleccionar todas las relaciones de términos huérfanas

SELECT tr.*, tt.*, wt.name, wt.slug FROM wp_term_relationships AS tr INNER JOIN wp_term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id INNER JOIN wp_terms AS wt ON tt.term_id = wt.term_id WHERE tt.taxonomy != 'link_category' AND tr.object_id NOT IN (SELECT ID FROM wp_posts);

Seleccionar todos los metadatos de publicaciones duplicados

El resultado mostrará el número de duplicaciones (columna count) de cualquier combinación de meta_key y meta_value para cualquier post_id.

SELECT COUNT(meta_id) AS count, post_id, meta_key, meta_value FROM wp_postmeta GROUP BY post_id, meta_key, meta_value HAVING count > 1;

Seleccionar todos los metadatos de usuario duplicados

El resultado mostrará el número de duplicaciones (columna count) de cualquier meta_key y meta_value de cualquier user_id.

SELECT COUNT(umeta_id) AS count, user_id, meta_key, meta_value FROM wp_usermeta GROUP BY user_id, meta_key, meta_value HAVING count > 1;

Seleccionar todos los metadatos de comentarios duplicados

El resultado mostrará el número de duplicaciones (columna count) de cualquier meta_key y meta_value de cualquier comment_id.

SELECT COUNT(meta_id) AS count, comment_id, meta_key, meta_value FROM wp_commentmeta GROUP BY comment_id, meta_key, meta_value HAVING count > 1;

Seleccionar todos los metadatos de términos duplicados

El resultado mostrará el número de duplicaciones (columna count) de cualquier meta_key y meta_value de cualquier term_id.

SELECT COUNT(meta_id) AS count, term_id, meta_key, meta_value FROM wp_termmeta GROUP BY term_id, meta_key, meta_value HAVING count > 1;

3) Limpiar las tablas de la base de datos predeterminadas de WordPress

Una instalación de WordPress por defecto tiene las siguientes tablas de base de datos:

  • wp_commentmeta
  • wp_comments
  • wp_links
  • wp_options
  • wp_postmeta
  • wp_posts
  • wp_terms
  • wp_termmeta
  • wp_term_relationships
  • wp_term_taxonomy
  • wp_usermeta
  • wp_users

Como cualquier otra tabla de base de datos de WordPress, estas pueden llenarse con información innecesaria que puedes limpiar.

wp_options

Esta es, con diferencia, la tabla más importante de WordPress, por lo que es crucial optimizarla. Si no sabes lo que estás haciendo, es posible que tu web deje de funcionar, ya que esta tabla contiene información no solo sobre los ajustes y configuraciones de tus plugins, sino también sobre el propio WordPress, como la URL del sitio o la estructura de enlaces permanentes. 

Aquí hay varias tareas de optimización que podemos hacer.

Eliminar datos transitorios

En WordPress, los datos transitorios son una forma para que los plugins almacenen datos temporalmente en caché en la base de datos, como por ejemplo los resultados de consultas complejas de bases de datos. Los datos transitorios ayudan a mejorar el rendimiento de tu sitio web porque reducen la cantidad de veces que tu página necesita ejecutar la misma consulta. 

Cuando un plugin crea un dato transitorio, opcionalmente establece una fecha de caducidad. Este es un paso tanto lógico (no querrías recuperar datos antiguos) como de mantenimiento (evitas el desorden en la base de datos). WordPress elimina el dato transitorio cuando el plugin lo solicita y WordPress detecta que se ha alcanzado la fecha de caducidad.

Pero hay un problema. ¿Qué sucede si un plugin crea muchas filas con datos transitorios, pero lo eliminas y el mismo plugin no se encarga de eliminar tales datos transitorios completamente? Lo que pasará es que tendrás muchos transitorios que no se volverán a solicitar nunca y, por lo tanto, no podrán caducar. Así pues, estos transitorios permanecerán en la base de datos durante años y no harán más que ocupar espacio innecesario. 

Puedes verificar manualmente qué datos transitorios pertenecen a qué plugin, pero dado que es trabajo de chinos, yo te recomiendo lo siguiente: 

  1. Elimina todos los transitorios con WP-Sweep.
  2. Espera alrededor de un mes.
  3. Comprueba otra vez cuántos transitorios tienes con WP-Sweep. Si tienes aproximadamente el mismo número, significa que los transitorios eliminados en realidad se han usado y se han recreado. Si tienes un número mucho más bajo, ¡felicidades!, has eliminado transitorios que no necesitabas.

Dado que los datos transitorios son solo datos cacheados, no debería haber ningún problema en eliminarlos. Sin embargo, deberías hacerlo solo cuando tu web tenga poca o nada de tráfico, especialmente si tienes una tienda online o usuarios potencialmente conectados.

Limpiar «autoloads»

Los datos cargados automáticamente son datos que tu WordPress tiene que coger cada vez que alguien abre una página de tu web, y se configuran con el campo de autoload en la tabla wp_options. En las versiones más recientes de WordPress (6.6 y posteriores), existen varias maneras de controlar si los datos se cargan automáticamente. Incluso si se utilizan términos antiguos como yes o no, WordPress los sabe interpretar. Internamente, WordPress convierte todas estas entradas en un conjunto estándar de valores como on, off, auto-on, auto-off, or auto, y decide el comportamiento final automáticamente con la función wp_determine_option_autoload_value(). Los autores de plugins y temas aún pueden forzar la carga o no carga automática de una configuración, pero en la mayoría de los casos WordPress se encarga de ello.

Como hemos comentado antes, la tabla wp_options contiene todo tipo de datos importantes para tu sitio de WordPress, como la URL del sitio, la configuración de los plugins, la configuración de tu tema, etc., pero a menudo también contiene datos que ya no se usan porque el plugin al cual tales datos pertenecían no limpió lo que debía limpiar al eliminarse. Teniendo en cuenta que uno de los principales problemas de los sitios web de WordPress es la gran cantidad de «autoloads» en la tabla wp_options (muchos desarrolladores configuran el campo de autoload de sus plugins/temas a yes por defecto, aunque teóricamente no todos los plugins deberían forzar la carga de sus datos en cada página), debemos priorizar la eliminación de «autoloads» para evitar una web lenta.

Eliminar «autoloads»

Así pues, nuestro objetivo tiene que ser localizar todos los «autoloads» que ya no se necesitan. El mejor plugin para esto, si no quieres ensuciarte las manos con phpMyAdmin, es Advanced DB Cleaner. En la pestaña Opciones, puedes ver toda la tabla wp_options, filtrar por los datos cargados automáticamente y eliminarlos de allí. Echemos un vistazo a cómo hacerlo.

1) Ve a Herramientas > WP DB Cleaner > Opciones.

2) Ordena de mayor tamaño a menor tamaño.

3) Ahora ve de arriba a abajo y busca solo las opciones donde la carga automática esté activada.

4) Para cada «autoload», búscalo en Google y averigua a qué pertenece. Puede ser un plugin, un tema o el propio WordPress. Bórralo solo si estás seguro de que no lo necesitas.

El tamaño total de los datos cargados automáticamente no debería exceder de 800 KB para evitar una advertencia en la herramienta de salud del sitio de WordPress, y nuestro objetivo debería ser tener menos de 500 KB. La pregunta es cómo podemos comprobar el tamaño total. Para esto tenemos un plugin creado por un servidor: Autoload Checker.

Comprobar el tamaño total de los «autoloads»

1) Instala el plugin Autoload Checker.

2) Ve a Herramientas > Autoload Checker.

3) En la parte de arriba te saldrá el tamaño total.

Eliminar opciones no utilizadas

Pero no solo es necesario limpiar las opciones cargadas automáticamente. Como con cualquier otra base de datos, tienes que deshacerte de todo lo que no se necesita. Muchos plugins dejan su configuración en la tabla wp_options después de la desinstalación y ni siquiera proporcionan un botón para eliminarla.

Puedes usar el plugin Advanced Database Cleaner para esto, pero la función que te permite determinar a qué plugin pertenece una determinada opción solo está disponible en su plan de pago. Es decir, si no quieres gastar dinero, tendrás que confiar en nuestro mejor amigo: Google. Ya sabes cómo va:

  • Ve a Herramientas > WP DB Cleaner > Opciones.
  • Busca en Google cada opción y averigua a qué pertenece. Puede ser un plugin, un tema o el mismo WordPress. Elimínala solo si estás seguro de que no la necesitas.

wp_posts

La tabla wp_posts contiene cada entrada, página o tipo de contenido personalizado en tu sitio. Así que, la forma más obvia de reducir su tamaño es eliminar todas las entradas o páginas innecesarias.

Sin embargo, dentro de esta tabla también se encuentran las revisiones. Las revisiones son versiones antiguas de tus entradas o páginas que se almacenan en la base de datos en caso de que quieras restaurarlas. A veces, el número de estas versiones puede llegar a ser demasiado grande, por lo que ocupa espacio en la base de datos y, en el peor de los casos, ralentiza tu sitio web.

Nuevamente, puedes usar WP-Sweep, pero ten en cuenta que no te permite mantener una cierta cantidad de revisiones. Eliminas o todo o nada. Si quieres mantener una cantidad específica de revisiones, puedes usar el plugin Advanced Database Cleaner y configurarlo para mantener la cantidad de días de revisiones que elijas.

wp_postmeta

Esta tabla de base de datos en especial es bastante problemática. No hay una forma obvia de limpiarla, por lo que todo debe hacerse a mano. Y no solo eso, es una tabla que tiende a crecer mucho y rápido, espcialmente si WooCommerce está en uso desde hace mucho tiempo (ya han solucionado el problema).

Desafortunadamente, para limpiar la tabla postmeta, tendremos que revisar todos los metadatos existentes y determinar si están actualmente en uso. Para ello utilizamos dos consultas SQL que podemos ejecutar desde phpMyAdmin u otro software de gestión de bases de datos. La primera consulta es la siguiente:

SELECT MAX(t1.post_id) AS `post_id`, MAX(t2.post_date) AS `Date`, SUBSTRING_INDEX(t1.meta_key, '_', 2) AS `Meta`, (SUM(LENGTH(meta_id)+LENGTH(post_id)+LENGTH(meta_key)+LENGTH(meta_value)))/1048567 AS `Size`, COUNT(*) AS `Count`
    FROM wp_postmeta AS t1
    JOIN wp_posts AS t2 
        ON t1.post_id = t2.ID
    WHERE meta_key NOT LIKE '\_%'
    GROUP BY `Meta`
    ORDER BY `Date` DESC;

La segunda consulta es exactamente la misma, solo que la cláusula WHERE se cambia para que se excluyan las líneas con un guión bajo inicial en el campo meta_key. Esto se hace porque los valores de meta_key se distinguen por un guión bajo inicial (para configuraciones secretas/predeterminadas) o la ausencia de este (para configuraciones accesibles para el usuario en el panel de administración), lo que requiere dos consultas.

SELECT MAX(t1.post_id) AS `post_id`, MAX(t2.post_date) AS `Date`, SUBSTRING_INDEX(t1.meta_key, '_', 2) AS `Meta`, (SUM(LENGTH(meta_id)+LENGTH(post_id)+LENGTH(meta_key)+LENGTH(meta_value)))/1048567 AS `Size`, COUNT(*) AS `Count`
    FROM wp_postmeta AS t1
    JOIN wp_posts AS t2 
        ON t1.post_id = t2.ID
    WHERE meta_key LIKE '\_%'
    GROUP BY `Meta`
    ORDER BY `Date` DESC;

Echemos un vistazo a un ejemplo de lo que obtenemos como resultado de la primera consulta y cómo proceder después. Receurda que debes proceder de la misma forma con la segunda consulta.

  • post_id nos muestra el ID de publicación más reciente al que pertenece el metadato en cuestión.
  • Date nos muestra la fecha del post_ID anterior. Mirando la fecha y el ID de la publicación, podemos determinar si los metadatos en cuestión se pueden eliminar o no. En el caso anterior, por ejemplo, no podemos eliminar los metadatos con la meta_key que contiene wp_featherlight porque los últimos metadatos se crearon recientemente (esto se está escribiendo en 2024) y el ID de la publicación a la que pertenecen es uno de los más recientes en la tabla posts. Y, bueno, también tengo instalado el plugin WP Featherlight…
  • Meta es el prefijo de cada grupo de metadatos. La consulta está diseñada para mostrar solo las dos primeras cadenas, cogiendo los guiones bajos como separadores. Esto nos facilita separar los grupos por plugin, tema o componente. Por ejemplo, wp_featherlight es el prefijo de todos los metadatos wp_featherlight_disable, pero también podría contener wp_featherlight_enable o cualquier otra cosa que empiece por wp_featherlight:
  • Size es el tamaño de los datos de cada grupo de prefijos, en megabytes (MB).
  • Count es el número de filas de cada grupo de prefijos.

En nuestro ejemplo, hemos determinado que no estamos usando publicize_twitter porque el último ID de publicación que las usó fue 20460, mientras que ya estamos en 37015. Además, esta publicación (20460) se creó en 2019, aproximadamente 5 años antes del momento en que se está escribiendo este artículo. Además, todos los datos de publicize_twitter pertenecen a Jetpack, que ya fue desinstalado en la web.

Por lo tanto, podemos ejecutar el comando DELETE para quitarlos todos. Asegúrate de ejecutar una consulta SELECT antes, para no eliminar nada importante.

SELECT * FROM wp_postmeta
    WHERE meta_key LIKE 'publicize_twitter%';
DELETE FROM wp_postmeta 
    WHERE meta_key LIKE 'publicize_twitter%';

Me gustaría agradecer a David Greenwald (rawkblog.com) por crear este magnífico artículo de donde he tomado inspiración.

oEmbed cache

WordPress almacena todos los datos de oEmbed en la base de datos para mejorar la velocidad de carga, que es básicamente el código que se necesita de recursos externos como YouTube, Twitter o Google Maps. Si hay muchas entradas antiguas eliminadas que usan oEmbed, podrían llenar la base de datos innecesariamente. En este caso, esta caché debe vaciarse.

Obviamente no puedes saber si hay muchas entradas antiguas eliminadas que han usado oEmbed. Por lo tanto, puedes limpiar esta caché de vez en cuando con seguridad con, una vez más, WP-Sweep.

wp_comments

Si quieres optimizar la tabla wp_comments la mejor manera es simplemente deshacerse del spam y de los comentarios eliminados. Ni siquiera necesitas un plugin para hacer esto. Simplemente accede a tu escritorio de WordPress y elimínalos de la sección de comentarios.

wp_commentmeta

Tendrás que seguir las mismas instrucciones que para la tabla postmeta, pero ejecutando las siguientes consultas. No dudes en consultar la sección wp_postmeta.

SELECT MAX(t1.comment_ID) AS `ID`, MAX(t2.comment_date) AS `Date`, SUBSTRING_INDEX(t1.meta_key, '_', 2) AS `Meta`, (SUM(LENGTH(meta_id)+LENGTH(t1.comment_ID)+LENGTH(meta_key)+LENGTH(meta_value)))/1048567 AS `Size`, COUNT(*) AS `Count`
    FROM wp_commentmeta AS t1
    JOIN wp_comments AS t2 
        ON t1.comment_ID = t2.comment_ID
    WHERE meta_key LIKE '\_%'
    GROUP BY `Meta`
    ORDER BY `Date` DESC;
SELECT MAX(t1.comment_ID) AS `ID`, MAX(t2.comment_date) AS `Date`, SUBSTRING_INDEX(t1.meta_key, '_', 2) AS `Meta`, (SUM(LENGTH(meta_id)+LENGTH(t1.comment_ID)+LENGTH(meta_key)+LENGTH(meta_value)))/1048567 AS `Size`, COUNT(*) AS `Count`
    FROM wp_commentmeta AS t1
    JOIN wp_comments AS t2 
        ON t1.comment_ID = t2.comment_ID
    WHERE meta_key NOT LIKE '\_%'
    GROUP BY `Meta`
    ORDER BY `Date` DESC;

wp_users

Al igual que con la tabla wp_comments, la mejor manera de reducir el tamaño de la tabla wp_users es eliminar usuarios. Los candidatos más obvios son los usuarios spam y los usuarios inactivos (aunque debes tener cuidado con los inactivos, deberías dejarlo claro en tus términos y condiciones que puedes hacerlo). Si el número de usuarios no es muy grande, simplemente puedes eliminarlos desde el panel de WordPress, pero si tienes muchos usuarios, tienes tres opciones.

  • Usar WP Bulk Delete.
  • Uar WP-CLI para eliminar usuarios por lotes y reasignar el contenido, por ejemplo: wp user delete $(wp user list --field=ID --search='*@ejemplo.%' --format=ids) --reassign=NUEVO_ID_USUARIO.
  • Usar phpMyAdmin. En este caso, tendrás que seguir estos pasos:
    • Ejecuta uno o más comandos SQL como DELETE FROM wp_users WHERE user_email = "%@example%";, reemplazando @example con cualquier patrón que reconozcas como spam (los usuarios inactivos no siguen ningún patrón, por lo que sólo puedes eliminarlos individualmente desde el panel de WordPress). Después de eliminar usuarios directamente con una consulta SQL, asegúrate de reasignar las publicaciones (por ejemplo, actualiza post_author) o utiliza un enfoque programático como wp_delete_user( $id, $reassign ) para evitar contenido huérfano.
    • Después de ejecutar el comando (o comandos), tendrás que eliminar los metadatos de usuario huérfanos, ya que los comandos en cuestión no los eliminan.

Desafortunadamente, es difícil identificar a los usuarios spam y a los usuarios inactivos. El spam es el más fácil de identificar porque normalmente sigue uno o más patrones, p. ej. direcciones de correo electrónico acabadas en .ru, combinaciones aleatorias de números y letras o cosas como NombreApellido@DominioDesconocido.com. Los usuarios inactivos, por otro lado, son usuarios que no tienen ninguna publicación o página asignada, ni medios, ni comentarios, etc. Sería útil saber la fecha del último inicio de sesión, pero es algo que no está integrado en WordPress de forma nativa.

wp_usermeta

Tendrás que seguir las mismas instrucciones que para la tabla postmeta, pero ejecutando las siguientes consultas. No dudes en consultar la sección wp_postmeta.

SELECT MAX(t1.user_id) AS `user_id`, MAX(t2.user_registered) AS `Date`,
SUBSTRING_INDEX(t1.meta_key, '_', 2) AS `Meta`,
(SUM(LENGTH(umeta_id)+LENGTH(user_id)+LENGTH(meta_key)+LENGTH(meta_value)))/1048567 AS `Size`, COUNT(*) AS `Count`
    FROM wp_usermeta AS t1
    JOIN wp_users AS t2
        ON t1.user_id = t2.ID
    WHERE meta_key LIKE '\_%'
    GROUP BY `Meta`
    ORDER BY `Date` DESC;
SELECT MAX(t1.user_id) AS `user_id`, MAX(t2.user_registered) AS `Date`,
SUBSTRING_INDEX(t1.meta_key, '_', 2) AS `Meta`,
(SUM(LENGTH(umeta_id)+LENGTH(user_id)+LENGTH(meta_key)+LENGTH(meta_value)))/1048567 AS `Size`, COUNT(*) AS `Count`
    FROM wp_usermeta AS t1
    JOIN wp_users AS t2
        ON t1.user_id = t2.ID
    WHERE meta_key NOT LIKE '\_%'
    GROUP BY `Meta`
    ORDER BY `Date` DESC;

wp_terms

Al igual que con la tabla wp_comments, la mejor manera de reducir el tamaño de la tabla wp_terms es eliminar términos, ya sean categorías o etiquetas (o cualquier término adicional que hayas creado o que haya creado otro plugin). El enfoque más obvio es eliminar términos que están vinculados a 0 publicaciones a través del panel de WordPress y que sabes que casi nunca se usarán.

No recomendio eliminar etiquetas a través de phpMyAdmin o una aplicación de administración de bases de datos, ya que estarás jugando con metadatos, relaciones y taxonomías de las tablas term_relationships, termmeta y term_taxonomy. Sin embargo, esta es la primera consulta que necesitarás si quieres ver los términos con 0 entradas:

SELECT * FROM wp_terms WHERE term_id IN (SELECT term_id FROM wp_term_taxonomy WHERE count = 0 );

Y luego, para borrarlos:

DELETE FROM wp_terms WHERE term_id IN (SELECT term_id FROM wp_term_taxonomy WHERE count = 0 );

Repito, si acabas de ejecutar estos comandos, deberás asegurarte de que no haya metadatos de términos, relaciones ni taxonomías huérfanos. Consulta la sección de eliminar metadatos huérfanos y duplicados.

wp_termmeta

You’ll need to follow the same instructions as for the wp_postmeta table, but you only need to execute the following query. Since the terms do not have a creation date, the results here are ordered by the size of the term metadata. The top results are the ones that take up the most space in the database. Feel free to refer to the wp_postmeta section.

Tendrás que seguir las mismas instrucciones que para la tabla wp_postmeta, pero solo necesitarás ejecutar la siguiente consulta. Dado que los términos no tienen fecha de creación, los resultados están ordenados por el tamaño de los metadatos del término. Los resultados son los que ocupan más espacio en la base de datos. No dudes en consultar la sección wp_postmeta.

SELECT MAX(t1.term_id) AS `term_id`,
SUBSTRING_INDEX(t1.meta_key, '_', 2) AS `Meta`,
(SUM(LENGTH(meta_id)+LENGTH(t1.term_id)+LENGTH(meta_key)+LENGTH(meta_value)))/1048567 AS `Size`, COUNT(*) AS `Count`
    FROM wp_termmeta AS t1
    JOIN wp_terms AS t2
        ON t1.term_id = t2.term_id
    GROUP BY `Meta`
    ORDER BY `Size` DESC;

wp_term_relationships

La única limpieza que puedes hacer en la tabla term_relationships es eliminar todas las filas huérfanas. Esta tabla almacena las relaciones entre artículos (u otros tipos de contenido) y los términos de taxonomía asociados. Básicamente, esta tabla sirve como una tabla de unión en una relación de muchos a muchos entre publicaciones y términos de taxonomía, por lo que nunca contiene datos inútiles no huérfanos; o el contenido es huérfano (y por lo tanto inútil) o no lo es.

Consulta la sección de eliminar metadatos huérfanos y duplicados.

wp_term_taxonomy

Lo mismo ocurre con term_relationships. Esta tabla contiene información acerca de los términos de taxonomía que se usan en una instalación de WordPress. Una taxonomía en WordPress se refiera a la manera en que el contenido esta categorizado, e incluye categorías, etiquetas y cualquier taxonomía personalizada definida por temas o plugins. Por lo tanto, en este caso te recomiendo consultar la sección de eliminar metadatos huérfanos y duplicados.

La tabla wp_links es parte del esquema de la base de datos de WordPress, pero no se usa comúnmente en las nuevas instalaciones de WordPress. Históricamente se utilizaba para almacenar datos relacionados con enlaces de blogroll, que eran colecciones de enlaces a otras webs o blogs que los blogueros querían mostrar en sus propios sitios.

4) Mejorar el auto-limpiado de las acciones programadas (Action Scheduler)

Las acciones programadas son una herramienta de procesamiento de tareas en segundo plano para WordPress, desarrollada y mantenida por Automattic. En inglés, a la herramienta se le llama Action Scheduler. Permite que los plugins (especialmente WooCommerce) programen y ejecuten tareas de forma asíncrona.

Quizás te preguntes: «¿Pero no tenemos ya WP-Cron?». Resulta que Action Scheduler utiliza WP-Cron de WordPress para procesar su propia cola, pero no depende de él. La cola puede ejecutarse de forma independiente, por ejemplo, mediante la ejecución directa de código, hooks personalizados o herramientas de línea de comandos. Esto la hace ideal para gestionar operaciones a gran escala o que consumen mucho tiempo, como procesar pagos, enviar correos electrónicos o sincronizar datos, sin ralentizar la experiencia del usuario, algo que ocurriría si solo dependiéramos de WP-Cron. Por cierto, esta es también la razón por la que deberías usar un cron de servidor.

¿Qué tablas de la base de datos pertenecen a Action Scheduler?

La biblioteca Action Scheduler es la responsable de crear y gestionar sus propias tablas de base de datos, no el núcleo de WordPress. Cuatro tablas se crean automáticamente cuando un plugin que incluye Action Scheduler (como WooCommerce) la inicializa:

  1. actionscheduler_actions: La tabla principal que almacena todas las tareas programadas (acciones), incluyendo su estado, programación y metadatos de ejecución.
  2. actionscheduler_claims: Registra qué acciones se están procesando actualmente, evitando la ejecución simultánea de la misma tarea.
  3. actionscheduler_groups: Permite agrupar acciones relacionadas para su organización y filtrado.
  4. actionscheduler_logs: Almacena los registros y el historial de ejecución de cada acción, lo cual resulta útil para tareas de depuración y la auditoría.

Cómo eliminar automáticamente más datos del Planificador de Acciones

Como puedes imaginarte, las dos tablas de la base de datos que pueden llenarse de datos innecesarios son actions y logs. Por defecto, Action Scheduler limpia estas dos tablas y elimina todos los registros con más de 31 días de antigüedad, y lo hace cada minuto. Sin embargo, el principal problema de las acciones programadas es que ignoran las acciones con estado «Falló» (una acción puede tener estado «Completo», «Pendiente» o «Falló»).

Ahora imagina que un plugin que usa el Action Scheduler falla repetidamente al ejecutar una acción específica, por la razón que sea. Si el plugin es muy activo, con el tiempo terminarás con miles y miles de acciones fallidas, incluso de hace años, ocupando espacio perpetuamente en la base de datos.

Por lo tanto, te recomiendo añadir el estado «Falló» a la limpieza automática del Action Scheduler. Añade lo siguiente a tu archivo functions.php:

add_filter( 'action_scheduler_default_cleaner_statuses', function ( $statuses ) {
	$statuses[] = 'failed';
	return $statuses;
} );

Ahora, si vas a Herramientas > Acciones programadas, verás que el contador de «Falló» disminuye en 20 cada minuto. Esta es la tasa de autolimpieza por defecto, que procesa 20 acciones a la vez.

¿Quieres limpiar más acciones cada vez? No hay problema. Añade el siguiente código al functions.php, pero ten cuidado: cuanto mayor sea el número, más tiempo tardará la limpieza y más memoria utilizará tu sitio, lo que podría provocar errores de memoria insuficiente y ralentizarlo. En este ejemplo, lo configuramos para eliminar 40 acciones a la vez:

add_filter( 'action_scheduler_cleanup_batch_size', function ( $batch_size ) {
	return 40;
} );

Y puedes reducir el período de retención de todos los registros (completos, fallidos o pendientes) para que, en lugar de 31 días, sea el tiempo que elijas. Por ejemplo, si lo configuras en 15 días, reducirás el tamaño de los registros a la mitad. Aquí tienes el código que debes añadir a functions.php. En este ejemplo, configuramos el tiempo de retención a una semana. Recuerda que el valor debe estar en segundos.

add_filter( 'action_scheduler_retention_period', function ( $period ) {
	return 604800; // 1 semana en segundos
} );

Eliminar manualmente las acciones programadas antiguas

Incluso con la limpieza automática, puede pasar que algunos registros se queden atascados y WordPress no los elimine automáticamente. O puede que simplemente quieras eliminarlos de inmediato. Puedes hacerlo manualmente desde Herramientas > Acciones programadas, pero para una limpieza más rápida y eficiente, puedes usar el plugin Easy Actions Scheduler Cleaner.

Después de instalar y ejecutar el plugin, puedes desinstalarlo. La limpieza automática generalmente no es necesaria, ya que WordPress debería eliminar los registros automáticamente (ver la sección anterior), y las notificaciones por correo electrónico que el plugin proporciona son innecesarias.

5) Limpiar las tablas de la BBDD personalizadas de WordPress

En esta sección, aprenderemos a limpiar tablas de base de datos que no pertenecen a WordPress. Normalmente, los plugins y temas crean tablas independientes para almacenar información específica, separándola de las tablas predeterminadas de WordPress, lo cual es una buena costumbre. Sin embargo, a menudo encontramos tablas que almacenan registros, datos de analítica web u otra información que nunca se elimina y que puede borrarse sin problemas. Dado que los desarrolladores suelen olvidar implementar funciones de limpieza, o a veces no les dan la prioridad necesaria, estas tablas siguen creciendo indefinidamente.

Esta sección está en constante desarrollo; en cuanto identifique un plugin con una tabla que cumpla con esta descripción, la añadiré aquí junto con las instrucciones para limpiarla.

Eliminar sesiones caducadas de WooCommerce

WooCommerce utiliza un sistema llamado sesiones para almacenar temporalmente datos sobre los visitantes y clientes mientras navegan por tu tienda, como el contenido del carrito, los cupones aplicados o el progreso del proceso de compra antes de que se finalize un pedido. En la práctica, una sesión de WooCommerce es un registro efímero almacenado en tu base de datos, específicamente en la tabla wp_woocommerce_sessions. Cada sesión incluye una marca de tiempo de caducidad (session_expiry), que determina cuándo deja de ser válida.

En teoría, WooCommerce debería eliminar automáticamente las sesiones caducadas, pero por alguna razón, es posible que te quedes con sesiones que llevan mucho tiempo caducadas.

Ejecuta la siguiente consulta SQL para comprobar cuántas sesiones caducadas tienes:

SELECT COUNT(*) 
FROM wp_woocommerce_sessions 
WHERE session_expiry < UNIX_TIMESTAMP();

Y luego, simplemente cambia la consulta a una instrucción DELETE:

DELETE 
FROM wp_woocommerce_sessions 
WHERE session_expiry < UNIX_TIMESTAMP();

6) Optimización de tablas

Las tablas de tu base de datos se comportan de alguna manera como las unidades de disco duro en Windows. ¿Recuerdas la palabra «desfragmentación» que solías ver en los ordenadores con Windows? Si ejecutas el comando OPTIMIZE TABLE en tablas MySQL, se reorganiza la memoria física de los datos de la tabla de la base de datos y los datos del índice asociado para ahorrar espacio en disco y mejorar la eficiencia al acceder a la tabla. Puedes optimizar las tablas de tu base de datos de WordPress de dos maneras.

Esto puede llevar algo de tiempo según el tamaño de los datos y los índices, pero mientras no se te vaya la luz, no pasará nada. Como decía, este proceso es similar a desfragmentar un ordenador.

WP-Sweep

Puedes volver a utilizar el plugin WP-Sweep y su opción «Optimize Tables».

phpMyAdmin

Si usas phpMyAdmin, puedes optimizar las tablas de tu base de datos con un solo clic. Para hacerlo, sigue estas instrucciones:

1) Inicia sesión en phpMyAdmin. Si no sabes cómo hacerlo, tu proveedor de alojamiento puede ayudarte.

2) Haz clic en Databases en el área superior.

3) Selecciona la base de datos correspondiente.

4) Haz clic en Check All (a menos que quieras seleccionar un grupo específico de tablas) y luego selecciona Optimize table.

5) Deberías recibir un mensaje de confirmación. ¡Y ya está!

5) Índices de alto rendimiento

Otro aspecto a optimizar en la base de datos son los índices. En resumen, un índice evita revisar cada fila de una tabla. Un índice funciona como el índice al final de un libro: en lugar de leer cada página para encontrar un tema, primero se revisa el índice para ver las páginas exactas donde aparece y luego se accede directamente a ellas en lugar de hojear todo el libro.

WordPress ya cuenta por defecto con algunos índices que funcionan bien en la mayoría de los sitios. Sin embargo, a medida que las webs crecen, estos índices se vuelven menos eficientes. Esto se nota especialmente en las tiendas online, pero básicamente cualquier sitio con tablas de base de datos enormes (muchos comentarios, muchas entradas, muchos pedidos, etc.) notará cierta lentitud en ciertas operaciones para solicitar datos, como al buscar una entrada en particular o los comentarios de un usuario específico. Y aquí es donde entra en juego el plugin Index WP MySQL For Speed: se instala una vez, se ejecuta y este realiza las modificaciones necesarias en los índices para convertirlos en «de alto rendimiento».

Si te interesa leer más sobre esto, sobre la historia de WordPress con los índices de las bases de datos y todos los cambios que tuvieron que realizar, así como sobre cómo el plugin mejora los índices, no dudes en consultar estas dos excelentes publicaciones:

Veamos cómo añadir índices de alto rendimiento a nuestra base de datos:

Método 1: A través de la interfaz del plugin

  1. Instala el plugin Index WP MySQL For Speed.
  2. Ve a Herramientas > Index MySQL.
  3. Averigua qué tablas son grandes. Cuando digo grandes, lo digo en serio. Las tablas pequeñas apenas verán mejoras y probablemente no merezca la pena hacer esto. Para tablas MySQL o MariaDB, como regla general, con menos de 100.000 filas probablemente no notarás ninguna diferencia. A partir de 100.000 filas, la tabla ya es lo suficientemente grande como para que los índices sean importantes.
  4. Selecciona todas las tablas relevantes para añadir índices:
  5. Haz clic en «Añadir claves ahora» o «Convertir claves ahora», según corresponda.
  6. Espera a que el plugin finalice.
  7. Ya puedes desinstalarlo.

Método 2: Mediante WP-CLI (recomendado)

Te recomiendo encarecidamente usar WP-CLI para realizar todo este proceso, ya que seguramente estés leyendo esto si el tamaño de las tablas de la BBDD es muy grande, y por tanto es probable que el proceso de añadir índices de alto rendimiento no termine correctamente desde la interfaz del plugin. Por lo tanto, te recomiendo familiarizarte con WP-CLI.

  1. Instala el plugin Index WP MySQL For Speed.
  2. Conéctate a tu servidor mediante SSH. Para ello, tendrás que pedir ayuda a tu proveedor de hosting.
  3. Una vez conectado, ve a la raíz de tu instalación de WordPress. Es donde se encuentran los directorios wp-contentwp-includes y wp-admin, normalmente dentro de la carpeta public_html.
  4. Ejecuta el comando que se te indica en la interfaz del plugin. Siguiendo el ejemplo de la captura de pantalla anterior, el comando sería wp index-mysql enable wp_postmeta
  5. Déjalo que haga su faena. ¡Ten paciencia! Tardará unos cuantos minutos si la tabla de la base de datos es grande.

¡Eso es todo!

6) Convertir tablas MyISAM a InnoDB

Optimizar tu base de datos de WordPress no solo se trata de limpiarla de datos sin usar, sino también de asegurarte de que las tablas usen el mejor motor de almacenamiento. Si tu base de datos todavía contiene tablas MyISAM, probablemente sea hora de convertirlas a InnoDB. Desde MySQL 5.5 (lanzado en 2010), InnoDB ha sido el motor de almacenamiento predeterminado por una razón: mejor rendimiento, mayor fiabilidad y características modernas.

MyISAM vs. InnoDB: ¿Por qué InnoDB es mejor?

Podría escribir un artículo completo sobre este tema, pero para resumirlo, las principales diferencias entre MyISAM e InnoDB son:

  • Integridad referencial: InnoDB admite claves foráneas para mantener la coherencia de los datos, mientras que MyISAM no. Esto significa que cuando una tabla (por ejemplo, listados) tiene una clave foránea (por ejemplo, id_propiedad) que apunta a otra tabla (por ejemplo, propiedades), las actualizaciones o eliminaciones en la tabla referenciada se reflejan en la tabla enlazada.
  • Transacciones: InnoDB permite el uso de transacciones con posibilidad de rollback; MyISAM no. Si una operación se interrumpe en una tabla InnoDB, el sistema de transacciones garantiza que las operaciones incompletas no se apliquen.
  • Bloqueo de registros: InnoDB utiliza bloqueo a nivel de fila para mejorar la concurrencia, mientras que MyISAM bloquea tablas completas. Esto significa que si estás leyendo una tabla grande o realizando operaciones de lectura/escritura frecuentes, MyISAM puede generar retrasos significativos en las consultas, afectando negativamente al rendimiento.
  • Fiabilidad: InnoDB es más resistente a fallos gracias a la recuperación automática, mientras que MyISAM es más propenso a la corrupción de datos. Antes de realizar cualquier cambio, InnoDB registra los datos en un archivo de sistema. Si ocurre un fallo, puede recuperarse automáticamente ejecutando esos registros de nuevo.
  • Índices de texto completo: MyISAM es compatible desde hace mucho tiempo la indexación de texto completo, mientras que InnoDB solo la introdujo en MySQL 5.6.4. Dicho esto, es otra razón para elegir un proveedor de hosting que ofrezca versiones actualizadas de MySQL o, mejor aún, MariaDB.

¿Cuándo se recomienda MyISAM?

Aunque InnoDB es generalmente mejor, MyISAM puede ser útil en algunas situaciones específicas:

  • Aplicaciones ligeras y con muchas lecturas: Si tu web se basa principalmente en lecturas de datos y no realiza muchas escrituras concurrentes, MyISAM puede ofrecer un rendimiento ligeramente superior en algunos casos.
  • Compatibilidad con sistemas antiguos: Algunos plugins o aplicaciones más antiguas pueden necesitar tablas MyISAM.

Cómo convertir tablas MyISAM a InnoDB

Si tu base de datos tiene tablas MyISAM, convertirlas a InnoDB es un proceso sencillo:

Método 1: Manualmente con phpMyAdmin

  1. Accede al panel de control de tu hosting y abre phpMyAdmin.
  2. Selecciona tu base de datos de WordPress.
  3. Haz clic en la pestaña SQL y ejecuta la siguiente consulta: ALTER TABLE nombre_de_tu_tabla ENGINE=InnoDB; Sustituye nombre_de_tu_tabla por el nombre real de la tabla. Repite el proceso para cada tabla MyISAM.

Cuando termines, no olvides ejecutar esta consulta para evitar que se creen tablas MyISAM en el futuro:

set persist_only disabled_storage_engines='MyISAM';

Método 2: Usando un plugin

Si prefieres un método más fácil, algunos plugins pueden encargarse de hacer esta conversión, como LiteSpeed Cache o mi favorito para esto: Simple MyISAM to InnoDB.

Simplemente instala el plugin, accede a su menú y selecciona las tablas que deseas convertir. Y deja que el plugin haga el trabajo por ti 🙂

Si ves un enlace de afiliado, te garantizo que es de un producto o servicio que realmente vale la pena. A diferencia de otras webs, aquí no se promociona nada solo porque paga más.

2 comentarios

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

  1. ¡Hola! Actualmente estoy tratando de entender cómo se lleva todo esto, ¡y lo explicas genial!.
    Sin embargo, este artículo está un poco anticuado. Aunque en la práctica sigue siendo funcional, se está recomendando instalar plugins que ya no son compatibles, o directamente que han sido abandonados. Se puede verificar desde Wordfence mismo, que recomienda desinstalarlos, como es el caso de «Plugins Garbage Collector (Database Cleanup)».

    Por el resto, un artículo muy recomendable! ^^

    • Hola Samuel,

      Gracias por tu comentario, me alegro que el artículo te sea útil 🙂

      Respecto a lo que comentas de los plugins, no hagas caso de lo que dice Wordfence. Yo aún uso Plugins Garbage Collector y no tengo ningún problema. No todo lo que dice Wordfence hay que seguirlo a rajatabla:

      – Lo que seguramente esté haciendo es verificar la última vez que se actualizaron los plugins, y si alguno pasa de X tiempo, entonces te recomienda desinstalarlo. Pero Wordfence no sabe si el plugin todavía funciona bien o no. Y como ya he dicho, Plugins Garbage Collector aún funciona bien.

      – De hecho te recomiendo que quites Wordfence, lo único que hace es ralentizar tu web. Hoy en día un plugin de seguridad es como el antivirus de Windows: no hace falta que instales ninguno. Te recomiendo que le eches un vistazo a este artículo: https://www.asistentewp.com/mejores-plugins-de-seguridad-gratuitos-para-wordpress-comparativa-de-rendimiento/

      ¡Un saludo!