web-dev-qa-db-ja.com

管理者:コアメタクエリによるページの編集が非常に遅い

私たちは投稿やページを編集しようとするときに本当に長いロード時間に気づいています。 Query Monitorを使用して、このWPコアクエリが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()

私たちの投稿タイプの一つは約20程度のカスタムフィールドを使っているので、私たちはたくさんのpostmetaを使います。多分私達はpostmetaにあまりに頼りすぎると言うでしょう、しかしこれはそれがポストのIDを選択さえしていないことを見て、非常に不利な質問のようです。

これはよくある問題ですか?フィルタを通してこの機能を無効にする方法はありますか?ご意見ありがとうございます。

10
psorensen

カスタムSQLをテストして、ロード時間にどのような影響があるかを確認したい場合は、次のクエリスワッピングを試してください。

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

ここではadd_meta_boxes_{$post_type}フックを使います。ここで$post_type = 'post'

ここではクエリ全体を交換しますが、動的制限をサポートするように調整することもできます。

うまくいけばあなたはあなたのニーズに合わせてこれを調整することができます。

更新:

この潜在的に遅いSQLコアクエリは、現在、WPバージョン4.3で調整されています。

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;

コアチケットをチェックしてください #24498 詳細については/。

5
birgire

関数のソースコードを閲覧すると、これがわかります。

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

postmeta_form_keysフックを使用すると、この非効率的なクエリをまったく呼び出さないように手動でキーを指定できます。

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

これを試してもらえますか。これは解決策ではありませんが、一時的な回避策です。

// 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
prosti