Administrator: bardzo wolna strona edycji spowodowana przez podstawowe zapytanie meta

11

Podczas edytowania postu lub strony zauważyliśmy naprawdę długi czas ładowania. Za pomocą Monitora zapytań stwierdziliśmy, że to podstawowe zapytanie WP zajmuje 15-20 sekund.

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

Używamy dużo postmeta, ponieważ jeden z naszych typów postów używa około 20 niestandardowych pól. Powiedziałbym, że może zbytnio polegamy na postmeta, ale wydaje się to bardzo przydatne, ponieważ nie wybiera nawet identyfikatora posta.

Czy to powszechny problem? Czy istnieje sposób na wyłączenie tej funkcji przez filtr? Dzięki za wszelkie uwagi.

psorensen
źródło
Czy dzieje się tak bez żadnych wtyczek i domyślnego motywu?
birgire,
Tak. Jak wspomniano powyżej, zidentyfikowałem wolne zapytanie jako należące do rdzenia WP. Dzięki funkcji w podanej przeze mnie odpowiedzi meta-pole niestandardowych pól jest wyłączone, co uniemożliwia uruchomienie zapytania.
psorensen
2
Widzę, że wiem, właśnie sprawdziłem meta_form()funkcję i jest to rzeczywiście wygenerowane zapytanie SQL z tej podstawowej funkcji. Możesz spróbować dodać własny niestandardowy metaboks ze zmianami w kodzie meta_form()i użyć tam sugerowanego zapytania SQL. Znalazłem ten zamknięty bilet trac # 8561 . Mógłbyś stworzyć kolejny bilet lub spróbować otworzyć go ponownie? PS: Zauważ, że strona nadrzędna wybierająca metaboks jest również problematyczna. Jeśli masz 1 milion stron, wszystkie z nich pojawią się jako wybrane opcje!
birgire,
2
Rozwiązanie zaproponowane w CSS-Tricks: css-tricks.com/…
psorensen
Ciekawe rozwiązanie, ale wygląda na to, że zastępuje całą meta_form()funkcję. Zaktualizowałem odpowiedź - podstawowe zapytanie SQL zostało dostosowane w WP 4.3. Czy widzisz wzrost wydajności dzięki temu nowemu zapytaniu SQL w porównaniu do naszego dodatkowego post_idograniczenia?
birgire,

Odpowiedzi:

5

Jeśli chcesz przetestować niestandardowy kod SQL, aby zobaczyć, jak wpływa on na czas ładowania, możesz wypróbować tę zamianę zapytania:

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

Tutaj używamy add_meta_boxes_{$post_type}haka, gdzie $post_type = 'post'.

W tym miejscu zamieniliśmy całe zapytanie, ale mogliśmy je również dostosować do obsługi limitu dynamicznego.

Mam nadzieję, że możesz to dostosować do swoich potrzeb.

Aktualizacja:

To potencjalnie wolne podstawowe zapytanie SQL zostało teraz dostosowane w wersji WP 4.3 od

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

do:

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;

Sprawdź bilet podstawowy # 24498, aby uzyskać więcej informacji.

birgire
źródło
2

Jeśli przejrzysz kod źródłowy funkcji, znajdziesz to:

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

Za pomocą postmeta_form_keyshaka możesz ręcznie określić klucze, aby całkowicie nie wywoływać tego nieefektywnego zapytania:

add_filter('postmeta_form_keys', function(){
    return ['your_meta_key'];
});
Dan K.
źródło
Ciekawy. Gdzie w kodzie źródłowym to istnieje?
psorensen
wp-admin / obejmuje / template.php: 595 od 4.4
markdwhite
2

Czy możesz to wypróbować? To nie jest rozwiązanie, ale tymczasowe obejście.

// 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
źródło
-1

Usunięcie metaboksów zapobiega również powolnemu zapytaniu.

function remove_metaboxes() {
     remove_meta_box( 'postcustom', 'page', 'normal' );
}
add_action('admin_menu', 'remove_metaboxes');
psorensen
źródło