Admin: page d'édition très lente causée par la méta-requête principale


11

Nous avons remarqué des temps de chargement très longs lors de la modification d'un article ou d'une page. En utilisant Query Monitor, nous avons constaté que cette requête de base WP prend jusqu'à 15-20 secondes.

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()

Nous utilisons beaucoup de postmeta car l'un de nos types de messages utilise environ 20 champs personnalisés. Je dirais que nous comptons peut-être trop sur postmeta, mais cela semble être une requête très inefficace, vu qu'il ne sélectionne même pas l'ID du message.

Est-ce un problème commun? Existe-t-il un moyen de désactiver cette fonction via un filtre? Merci pour toute contribution.


Est-ce que cela se produit sans plugins et sans thème par défaut?
birgire

Oui. Comme mentionné ci-dessus, j'ai identifié la requête lente comme appartenant au noyau WP. Avec la fonction dans la réponse que j'ai fournie, la zone de méta des champs personnalisés est désactivée, ce qui empêche l'exécution de la requête.
psorensen

2
Je le vois, je viens de vérifier la meta_form()fonction et c'est bien la requête SQL générée à partir de cette fonction principale. Vous pouvez essayer d'ajouter votre propre métabox personnalisée avec des modifications au code meta_form()et d'y utiliser votre requête SQL suggérée. J'ai trouvé ce ticket trac fermé # 8561 . Vous pourriez peut-être créer un autre ticket ou essayer de rouvrir celui-ci? PS: Notez que la page parent qui sélectionne la métabox est également problématique. Si vous avez 1 million de pages, toutes s'afficheront comme options de sélection!
birgire

2
Une solution proposée sur CSS-Tricks: css-tricks.com/…
psorensen

Solution intéressante là-bas, mais il semble qu'elle remplace toute la meta_form()fonction. J'ai mis à jour la réponse - la requête SQL principale a été ajustée dans WP version 4.3. Voyez-vous un gain de performances avec cette nouvelle requête SQL par rapport à notre post_idrestriction supplémentaire ?
birgire

Réponses:


5

Si vous souhaitez tester votre SQL personnalisé pour voir comment il affecte le temps de chargement, vous pouvez essayer l'échange de requêtes:

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

Ici, nous utilisons le add_meta_boxes_{$post_type}crochet, où $post_type = 'post'.

Ici, nous échangeons la requête entière, mais nous aurions également pu l'ajuster pour prendre en charge la limite dynamique.

J'espère que vous pourrez ajuster cela à vos besoins.

Mettre à jour:

Cette requête SQL potentiellement lente, a maintenant été ajustée dans WP version 4.3 à partir de

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

à:

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;

Consultez le ticket principal # 24498 pour plus d'informations.


2

Si vous parcourez le code source de la fonction, vous trouverez ceci:

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

En utilisant le postmeta_form_keyshook, vous pouvez spécifier manuellement les clés pour éviter d'appeler complètement cette requête inefficace:

add_filter('postmeta_form_keys', function(){
    return ['your_meta_key'];
});

Intéressant. Où cela existe-t-il dans le code source?
psorensen

wp-admin / includes / template.php: 595 à partir de 4.4
markdwhite

2

Pouvez-vous essayer cela. Ce n'est pas une solution, mais une solution temporaire.

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

-1

La suppression des métaboxes empêche également la requête lente.

function remove_metaboxes() {
     remove_meta_box( 'postcustom', 'page', 'normal' );
}
add_action('admin_menu', 'remove_metaboxes');
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.