管理员:核心元查询导致编辑页面非常慢


11

我们一直注意到在编辑帖子或页面时加载时间非常长。使用查询监视器,我们发现此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()

我们确实使用了很多postmeta,因为我们的一种帖子类型使用了大约20个左右的自定义字段。我想说也许我们过分依赖postmeta,但这似乎是一个非常低效的查询,因为它甚至没有选择帖子的ID。

这是常见问题吗?有没有办法通过过滤器禁用此功能?感谢您的任何投入。


在没有任何插件和默认主题的情况下会发生这种情况吗?
比尔吉里(Birgire),2015年

是的,它确实。如上所述,我已经确定慢查询属于WP核心。使用我提供的答案中的功能,自定义字段元框被禁用,这阻止了查询的运行。
psorensen

2
我知道,我刚刚签出了meta_form()函数,这确实是从该核心函数生成的SQL查询。您可以尝试添加对代码进行修改的自定义元框,然后在meta_form()其中使用建议的SQL查询。我发现这张#8561封闭式火车票。您也许可以创建另一张票证或尝试重新打开该票证? PS:请注意,父页面选择元框也是有问题的。如果您有100万页,那么所有页面都会显示为选择选项!
比尔吉里(Birgire)

2
CSS-Tricks上提出的一种解决方案:css-tricks.com/…–
psorensen

有趣的解决方案,但看起来它正在替换整个meta_form()功能。我更新了答案-核心SQL查询已在WP版本4.3中进行了调整。与我们的附加post_id限制相比,您认为此新SQL查询的性能有所提高吗?
birgire

Answers:


5

如果要测试自定义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}钩子where $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了解更多信息。


2

如果浏览该函数的源代码,则会发现以下内容:

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

使用postmeta_form_keys挂钩可以手动指定键,从而避免完全调用此效率低下的查询:

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

有趣。这在源代码中的哪里存在?
psorensen

wp-admin / includes / template.php:595(自4.4版开始)
markdwhite '16

2

你可以尝试一下吗 这不是解决方案,而是临时解决方法。

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

删除元框还可以防止查询缓慢。

function remove_metaboxes() {
     remove_meta_box( 'postcustom', 'page', 'normal' );
}
add_action('admin_menu', 'remove_metaboxes');
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.