Admin: Sehr langsame Bearbeitungsseite, die durch eine zentrale Metaabfrage verursacht wird

11

Wir haben sehr lange Ladezeiten beim Bearbeiten eines Posts oder einer Seite festgestellt. Bei Verwendung von Query Monitor haben wir festgestellt, dass diese WP-Kernabfrage bis zu 15-20 Sekunden dauert.

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

Wir verwenden viel Postmeta, da einer unserer Post-Typen ungefähr 20 benutzerdefinierte Felder verwendet. Ich würde sagen, vielleicht verlassen wir uns zu sehr auf Postmeta, aber dies scheint eine sehr unzulängliche Abfrage zu sein, da nicht einmal die ID des Posts ausgewählt wird.

Ist das ein häufiges Problem? Gibt es eine Möglichkeit, diese Funktion über einen Filter zu deaktivieren? Vielen Dank für jede Eingabe.

Psorensen
quelle
Geschieht dies ohne Plugins und das Standardthema?
Birgire
Ja tut es. Wie oben erwähnt, habe ich die langsame Abfrage als zum WP-Kern gehörend identifiziert. Mit der Funktion in der Antwort, die ich angegeben habe, ist das Meta-Feld für benutzerdefinierte Felder deaktiviert, wodurch die Ausführung der Abfrage verhindert wird.
Psorensen
2
Ich sehe es weiß, ich habe gerade die meta_form()Funktion ausgecheckt und dies ist in der Tat die generierte SQL-Abfrage von dieser Kernfunktion. Sie können versuchen, eine eigene benutzerdefinierte Metabox mit Änderungen am Code hinzuzufügen meta_form()und dort Ihre vorgeschlagene SQL-Abfrage zu verwenden. Ich habe dieses geschlossene Trac-Ticket Nr. 8561 gefunden . Sie könnten vielleicht ein anderes Ticket erstellen oder versuchen, dieses wieder zu öffnen? PS: Beachten Sie, dass die Auswahl der Metabox auf der übergeordneten Seite ebenfalls problematisch ist. Wenn Sie 1 Million Seiten haben, werden alle als ausgewählte Optionen angezeigt!
Birgire
2
Eine auf CSS-Tricks vorgeschlagene Lösung: css-tricks.com/…
psorensen
Interessante Lösung dort, aber es sieht so aus, als würde sie die gesamte meta_form()Funktion ersetzen . Ich habe die Antwort aktualisiert - die SQL-Kernabfrage wurde in WP Version 4.3 angepasst. Sehen Sie bei dieser neuen SQL-Abfrage einen Leistungsgewinn im Vergleich zu unserer zusätzlichen post_idEinschränkung?
Birgire

Antworten:

5

Wenn Sie Ihr benutzerdefiniertes SQL testen möchten, um festzustellen, wie sich dies auf die Ladezeit auswirkt, können Sie diese Abfrage austauschen:

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

Hier benutzen wir den add_meta_boxes_{$post_type}Haken, wo $post_type = 'post'.

Hier tauschen wir die gesamte Abfrage aus, aber wir hätten sie auch anpassen können, um das dynamische Limit zu unterstützen.

Hoffentlich können Sie dies an Ihre Bedürfnisse anpassen.

Aktualisieren:

Diese möglicherweise langsame SQL-Kernabfrage wurde jetzt in WP Version 4.3 von angepasst

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

zu:

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;

Schauen Sie sich den Kern Ticket # 24498 für weitere Informationen.

Birgire
quelle
2

Wenn Sie den Quellcode der Funktion durchsuchen, finden Sie Folgendes:

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

Mit dem postmeta_form_keysHook können Sie die Schlüssel manuell angeben, um zu vermeiden, dass diese ineffiziente Abfrage insgesamt aufgerufen wird:

add_filter('postmeta_form_keys', function(){
    return ['your_meta_key'];
});
Dan K.
quelle
Interessant. Wo im Quellcode existiert das?
Psorensen
wp-admin / includes / template.php: 595 ab 4.4
markdwhite
2

Kannst du das ausprobieren? Dies ist keine Lösung, sondern eine vorübergehende Problemumgehung.

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

Das Entfernen der Metaboxen verhindert auch die langsame Abfrage.

function remove_metaboxes() {
     remove_meta_box( 'postcustom', 'page', 'normal' );
}
add_action('admin_menu', 'remove_metaboxes');
Psorensen
quelle