Admin: página de edição muito lenta causada pela meta consulta principal

11

Observamos tempos de carregamento muito longos ao editar uma postagem ou página. Usando o Query Monitor, descobrimos que essa consulta principal do WP está levando entre 15 e 20 anos.

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 muito postmeta, pois um dos nossos tipos de postagem usa cerca de 20 campos personalizados. Eu diria que talvez confiemos demais no postmeta, mas isso parece ser uma consulta muito ineficiente, já que nem sequer está selecionando o ID da postagem.

Esse é um problema comum? Existe uma maneira de desativar esta função através de um filtro? Obrigado por qualquer entrada.

psorensen
fonte
Isso acontece sem nenhum plug-in e o tema padrão?
Birgire
Sim. Como mencionado acima, identifiquei a consulta lenta como pertencente ao núcleo do WP. Com a função na resposta que forneci, a caixa meta de campos personalizados é desativada, o que impede a execução da consulta.
Psorensen
2
Pelo que sei, acabei de verificar a meta_form()função e essa é realmente a consulta SQL gerada a partir dessa função principal. Você pode tentar adicionar sua própria metabox personalizada com modificações no código meta_form()e usar sua consulta SQL sugerida. Encontrei este bilhete trac fechado nº 8561 . Você poderia criar outro ticket ou tentar reabrir esse? PS: Observe que a página pai que seleciona metabox também é problemática. Se você tiver 1 milhão de páginas, todas elas serão exibidas como opções selecionadas!
Birgire
2
Uma solução proposta em CSS-Tricks: css-tricks.com/…
psorensen
Solução interessante lá, mas parece que está substituindo toda a meta_form()função. Atualizei a resposta - a consulta SQL principal foi ajustada na versão 4.3 do WP. Você vê algum ganho de desempenho com essa nova consulta SQL em comparação com nossa post_idrestrição adicional ?
precisa saber é

Respostas:

5

Se você quiser testar seu SQL personalizado para ver como isso afeta o tempo de carregamento, tente esta troca de consulta:

/**
 * 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;
    } );                                                            
} );

Aqui usamos o add_meta_boxes_{$post_type}gancho, onde $post_type = 'post'.

Aqui trocamos toda a consulta, mas também poderíamos ter ajustado para suportar o limite dinâmico.

Espero que você possa ajustar isso às suas necessidades.

Atualizar:

Essa consulta principal potencialmente lenta do SQL foi ajustada no WP versão 4.3 de

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

para:

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;

Confira o ticket principal # 24498 para obter mais informações.

Birgire
fonte
2

Se você navegar pelo código fonte da função, encontrará o seguinte:

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

Usando o postmeta_form_keysgancho, você pode especificar manualmente as chaves para evitar chamar completamente essa consulta ineficiente:

add_filter('postmeta_form_keys', function(){
    return ['your_meta_key'];
});
Dan K
fonte
Interessante. Onde no código fonte isso existe?
Psrensen
wp-admin / includes / template.php: 595 a partir de 4.4
markdwhite 8/16
2

Você pode tentar isso? Esta não é uma solução, mas uma solução temporária.

// 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
fonte
-1

A remoção dos metaboxes também impede a consulta lenta.

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