Administrador: página de edición muy lenta causada por una meta consulta central

11

Hemos notado tiempos de carga realmente largos al editar una publicación o página. Usando Query Monitor, descubrimos que esta consulta central de WP tarda más de 15-20.

SELECT meta_key 
FROM wp_postmeta 
GROUP BY meta_key 
HAVING meta_key NOT LIKE '\\_%' 
ORDER BY meta_key 
LIMIT 30

caller: 
meta_form()
post_custom_meta_box()
do_meta_boxes()

Usamos una gran cantidad de postmeta, ya que uno de nuestros tipos de publicación usa alrededor de 20 campos personalizados. Diría que tal vez dependemos demasiado de postmeta, pero esto parece una consulta muy poco eficiente, ya que ni siquiera está seleccionando la ID de la publicación.

¿Es este un problema común? ¿Hay alguna forma de desactivar esta función a través de un filtro? Gracias por cualquier aportación.

psorensen
fuente
¿Esto sucede sin complementos y el tema predeterminado?
Birgire
Si lo hace Como se mencionó anteriormente, he identificado la consulta lenta como perteneciente al núcleo de WP. Con la función en la respuesta que proporcioné, el cuadro meta de campos personalizados está deshabilitado, lo que impide que se ejecute la consulta.
psorensen
2
Ya lo veo, acabo de comprobar la meta_form()función y esta es realmente la consulta SQL generada a partir de esa función central. Puede intentar agregar su propio metabox personalizado con modificaciones en el código meta_form()y usar allí su consulta SQL sugerida. Encontré este boleto de trac cerrado # 8561 . ¿Quizás podría crear otro boleto o intentar reabrir este? PD: Tenga en cuenta que la página principal que selecciona metabox también es problemática. Si tienes 1 millón de páginas, ¡todas aparecerán como opciones seleccionadas!
Birgire
2
Una solución propuesta en CSS-Tricks: css-tricks.com/…
psorensen
Solución interesante allí, pero parece que está reemplazando toda la meta_form()función. Actualicé la respuesta: la consulta SQL central se ha ajustado en la versión 4.3 de WP. ¿Ve alguna ganancia de rendimiento con esta nueva consulta SQL en comparación con nuestra post_idrestricción adicional ?
Birgire

Respuestas:

5

Si desea probar su SQL personalizado para ver cómo afecta el tiempo de carga, puede intentar este intercambio de consultas:

/**
 * Restrict the potential slow query in the meta_form() to the current post ID.
 *
 * @see http://wordpress.stackexchange.com/a/187712/26350
 */

add_action( 'add_meta_boxes_post', function( $post )
{
    add_filter( 'query', function( $sql ) use ( $post )
    {
        global $wpdb;
        $find = "SELECT meta_key
                 FROM $wpdb->postmeta
                 GROUP BY meta_key 
                 HAVING meta_key NOT LIKE '\\\_%'
                 ORDER BY meta_key 
                 LIMIT 30";
        if(    preg_replace( '/\s+/', ' ', $sql ) === preg_replace( '/\s+/', ' ', $find )
            && $post instanceof WP_Post  
        ) {
            $post_id = (int) $post->ID;
            $sql  = "SELECT meta_key
                     FROM $wpdb->postmeta
                     WHERE post_id = {$post_id}
                     GROUP BY meta_key
                     HAVING meta_key NOT LIKE '\\\_%'
                     ORDER BY meta_key
                     LIMIT 30";
        }
        return $sql;
    } );                                                            
} );

Aquí usamos el add_meta_boxes_{$post_type}gancho, donde $post_type = 'post'.

Aquí intercambiamos toda la consulta, pero también podríamos haberla ajustado para admitir el límite dinámico.

Esperemos que pueda ajustar esto a sus necesidades.

Actualizar:

Esta consulta principal de SQL potencialmente lenta, ahora se ha ajustado en WP versión 4.3 de

SELECT meta_key 
FROM wp_postmeta 
GROUP BY meta_key 
HAVING meta_key NOT LIKE '\\_%' 
ORDER BY meta_key 
LIMIT 30

a:

SELECT DISTINCT meta_key
FROM wp_postmeta
WHERE meta_key NOT BETWEEN '_' AND '_z'
HAVING meta_key NOT LIKE '\_%'
ORDER BY meta_key
LIMIT 30;

Echa un vistazo al boleto principal # 24498 para obtener más información.

Birgire
fuente
2

Si navega por el código fuente de la función, encontrará esto:

$keys = apply_filters( 'postmeta_form_keys', null, $post );
if ( null === $keys ) {
    ...      
}

Usando el postmeta_form_keysenlace puede especificar manualmente las claves para evitar llamar a esta consulta ineficiente por completo:

add_filter('postmeta_form_keys', function(){
    return ['your_meta_key'];
});
Dan K
fuente
Interesante. ¿Dónde en el código fuente existe esto?
psorensen
wp-admin / includes / template.php: 595 a partir del 4.4
markdwhite
2

¿Puedes probar esto? Esta no es una solución, sino una solución temporal.

// disable big slowdown http://wordpress.stackexchange.com/questions/187612/admin-very-slow-edit-page-caused-by-core-meta-query
function dj_limit_postmeta( $string, $post ) {
    return array(null);
}
add_filter( 'postmeta_form_keys', 'dj_limit_postmeta', 10, 3 );
prosti
fuente
-1

Eliminar los metaboxes también evita la consulta lenta.

function remove_metaboxes() {
     remove_meta_box( 'postcustom', 'page', 'normal' );
}
add_action('admin_menu', 'remove_metaboxes');
psorensen
fuente