
Tienes caché, imágenes optimizadas y un buen hosting, pero ciertas páginas siguen tardando: el buscador, el listado de productos con filtros, el escritorio. Cuando la lentitud aparece solo en algunas pantallas, casi siempre el culpable es una consulta a la base de datos.
La buena noticia es que esas consultas se pueden encontrar con nombre y apellido: qué consulta es, cuánto tarda y qué plugin la hizo.
Nivel 1: Query Monitor (para todos)
Instala el plugin gratuito Query Monitor. Agrega un menú en la barra de administración que muestra, en cada página que visitas como administrador:
- Cuántas consultas se hicieron y cuánto tardaron en total.
- Consultas lentas, marcadas en rojo.
- Consultas duplicadas: la misma consulta repetida muchas veces, típico de un plugin mal hecho.
- Por componente: cuánto tiempo de base de datos consume cada plugin y el tema.
Abre la página lenta, despliega Query Monitor y ve a Consultas por componente. Si un plugin se lleva el 80 % del tiempo, ya sabes por dónde empezar.
Query Monitor solo se muestra a administradores, así que puedes usarlo en un sitio en producción. Aun así, desactívalo cuando termines: también consume recursos.
Nivel 2: un registro de consultas lentas hecho por ti
Query Monitor solo ve lo que tú visitas. Si la lentitud aparece en horas punta o con clientes, necesitas registrar lo que pasa con todos. Este mu-plugin guarda en un archivo cada consulta que supere el umbral que elijas.
Primero, activa temporalmente el registro de consultas en wp-config.php:
define( 'SAVEQUERIES', true );
Luego crea wp-content/mu-plugins/cwp-consultas-lentas.php:
<?php
/**
* Plugin Name: Registro de consultas lentas (Curso WordPress)
* Description: Anota en wp-content/consultas-lentas.log las consultas de más de 0,2 s.
*/
const CWP_UMBRAL_SEGUNDOS = 0.2;
add_action( 'shutdown', function () {
global $wpdb;
if ( ! defined( 'SAVEQUERIES' ) || ! SAVEQUERIES || empty( $wpdb->queries ) ) {
return;
}
$url = isset( $_SERVER['REQUEST_URI'] ) ? $_SERVER['REQUEST_URI'] : 'cli';
foreach ( $wpdb->queries as $q ) {
list( $sql, $tiempo, $origen ) = $q;
if ( $tiempo < CWP_UMBRAL_SEGUNDOS ) {
continue;
}
$linea = sprintf(
"[%s] %.3fs %s\n SQL: %s\n Origen: %s\n",
gmdate( 'Y-m-d H:i:s' ),
$tiempo,
$url,
preg_replace( '/\s+/', ' ', $sql ),
$origen
);
error_log( $linea, 3, WP_CONTENT_DIR . '/consultas-lentas.log' );
}
} );
Déjalo funcionando unas horas en un momento de tráfico normal y revisa el archivo. La línea Origen muestra la cadena de funciones que llamó a la consulta, y ahí aparece el nombre del plugin o del archivo del tema.
Esto es temporal. SAVEQUERIES guarda todas las consultas en memoria y vuelve el sitio algo más lento. Cuando termines, quita la constante, borra el mu-plugin y borra el archivo .log, que además no debe quedar a la vista de nadie.
Nivel 3: el registro de MySQL en tu VPS
Si administras tu propio servidor con cPanel/WHM, MySQL o MariaDB pueden registrar las consultas lentas de todos los sitios del servidor. Por SSH como root, agrega a /etc/my.cnf, dentro de la sección [mysqld]:
slow_query_log = 1
slow_query_log_file = /var/lib/mysql/consultas-lentas.log
long_query_time = 1
Reinicia el servicio y, después de unas horas, pide un resumen agrupado:
/scripts/restartsrv_mysql
# Las 10 consultas que más tiempo total consumieron
mysqldumpslow -s t -t 10 /var/lib/mysql/consultas-lentas.log
Para entender por qué una consulta es lenta, ejecútala en phpMyAdmin con EXPLAIN delante. Si en la columna rows ves cientos de miles y en key dice NULL, MySQL está leyendo la tabla entera porque no tiene un índice que le sirva.
Los 6 culpables que más se repiten
- Búsquedas en campos personalizados con
LIKE '%texto%'. La tablawp_postmetano tiene índice sobre los valores. Si un filtro de productos busca así, cada búsqueda recorre la tabla completa. Solución: usar taxonomías en vez de campos para todo lo que se filtra (color, talla, marca). orderby => 'rand'. Ordenar al azar obliga a MySQL a leer todo. Mejor elige al azar en PHP entre unos pocos IDs.posts_per_page => -1. «Traer todo» funciona con 50 entradas y revienta con 50.000. Pagina siempre.- Contar el total sin necesitarlo. Si no muestras paginación, agrega
'no_found_rows' => truea tu consulta. - Opciones autoload gigantes. No es una consulta lenta, pero pesa en todas. Revisa la tabla
wp_options. - Tablas sin los índices adecuados. El plugin gratuito Index WP MySQL For Speed agrega índices mejores a las tablas de WordPress. Haz respaldo antes.
Un ejemplo de consulta bien escrita para un listado que no necesita paginación:
$consulta = new WP_Query( array(
'post_type' => 'product',
'posts_per_page' => 12,
'no_found_rows' => true, // no calcula el total de páginas
'fields' => 'ids', // solo IDs si no necesitas todo el objeto
'update_post_term_cache' => false, // no carga categorías si no las muestras
) );
¿Encontraste una consulta lenta y no sabes cómo arreglarla? Pégala en el foro junto con el resultado de EXPLAIN y la revisamos entre todos.





