【问题标题】:How to optimize WP_Query (includes CPT and ACF)如何优化 WP_Query(包括 CPT 和 ACF)
【发布时间】:2019-07-18 17:10:38
【问题描述】:

我一直在构建我的网站,今天正在使用 WP 插件 QueryMonitor 测试性能。一个特定页面的页面加载时间为 30 秒!在该页面上,我想从两种自定义帖子类型中打印出列表 - 我有两个查询。一种自定义帖子类型有超过 3000 个帖子要通过,另一种可能有 400 个要通过。所有帖子也都有 ACF 字段,我主要在页面上打印这些 ACF 字段。

QueryMonitor 给我: 页面生成时间 29,4764 98.3% 的 30 秒限制

内存使用峰值 14 392 KB 131 072 kB 限制的 11,0%

数据库查询时间 29,3400

数据库查询 总计:37

缓存还没有打开,但是页面通常只访问一次等等,所以缓存可能不是答案。

我需要分页,所以 no_found_rows 不是答案。对于已经设置的另一个查询,它加快了页面速度。

我的问题查询如下所示:

$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
$args = array(
    'posts_per_page' => 25,
    'post_type'      => 'horse',
    'paged'          => $paged,
    'meta_query'     => array(
        'relation' => 'AND',
        array(
            'key'     => 'owner_id_num',
            'value'   => $userid,
            'compare' => '=',
        ),
        array(
            'key'     => 'show_horse_profile',
            'value'   => '1',
            'compare' => '=',
        ),
    )
);
// query
$the_query = new WP_Query( $args );

我只是想知道如何加快查询速度。现在需要很多时间。

// 编辑。尝试自定义查询,出现错误“['on clause' 中的未知列 'wp_posts.ID']”。无法通过它...

SELECT $wpdb->posts.* 
FROM $wpdb->posts, $wpdb->postmeta, $wpdb->postmeta AS mt1
WHERE $wpdb->posts.ID = $wpdb->postmeta.post_id 

AND $wpdb->postmeta.meta_key = 'owner_id_num'   
AND $wpdb->postmeta.meta_value = $userid
AND mt1.meta_key = 'show_horse_profile'
AND mt1.meta_value = '1'
AND $wpdb->posts.post_status = 'publish' 
AND $wpdb->posts.post_type = 'horse'

ORDER BY $wpdb->posts.post_date DESC

我正在尝试打印:

$total = $wpdb->get_var( "SELECT COUNT(1) FROM (${query}) AS combined_table" );
$items_per_page = $posts_per_page;
$page = isset( $_GET['cpage'] ) ? abs( (int) $_GET['cpage'] ) : 1;
$offset = ( $page * $items_per_page ) - $items_per_page;
$latestposts = $wpdb->get_results( $query . " LIMIT ${offset}, ${items_per_page}" );
?>
<table class="table horse-list-profile">
    <thead>
    <tr>
        <th>Hevonen</th>
        <th>Painotus</th>
        <th>Talli</th>
        <th>Ensiarvostelutulos</th>
    </tr>
    </thead>

<?php
foreach ($latestposts as $currentPost) {
    $breed_ID = get_field("breed");
    $breed = get_field("short", $breed_ID);
    $disc = get_field_object("discipline");
    $disc_value = $disc['value'];
    $disc_label = $disc['choices'][ $disc_value ];
    $skp = get_field_object('sex');
    $skp_value = $skp['value'];
    if ($skp_value == '0') { $sex = 't'; }
    else if ($skp_value == '1') { $sex = 'o'; }
    else if ($skp_value == '2') { $sex = 'r'; }
    ?>
    <tr>
        <td><?php echo $breed; ?>-<?php echo $sex; ?> <a href="<?php echo get_post_permalink(); ?>"><?php the_title(); ?></a></td>
        <td><?php echo $disc_label; ?></td>
        <td><?php if(get_field("stable_id", get_the_ID())) { echo get_the_title(get_field("stable_id", get_the_ID())); } else { echo '-'; } ?></td>
        <td><strong><?php echo get_field("basic_evaluation_grade"); ?></strong> <small><?php echo get_field("basic_evaluation_points"); ?>/1900p.</small></td>
    </tr>
<?php
}
?>
</table>

【问题讨论】:

  • 页面上共有 37 个查询正在运行。其中最耗时的查询是什么?如果您认为上述查询仅导致此问题,请评论该查询并再次检查页面加载时间。
  • 您也可以将当前查询替换为自定义查询,这样也可以减少时间。我已经在多个网站上应用了这个。另外,尝试在自定义查询中获取 ACF 字段。
  • @SamiAhmedSiddiqui 最耗时的查询是我发布的查询,需要 27 秒。您能否详细说明自定义查询的含义 - 如下所示:codex.wordpress.org/…
  • 这个问题有进展吗?
  • 请让我知道您仍在进行优化或已完成优化。我喜欢解决优化和安全问题。

标签: wordpress performance pagespeed


【解决方案1】:

基于@SamiAhmedSiddiqui 的评论:

代码包含一个带有自定义分页菜单的自定义查询:

这就是我为我的网站制作它的方式,但也许你可以找到一些用处!

$posts_per_page = 10;
switch (filter_input(INPUT_GET, 'ppp')) {  
        case '10':
            $posts_per_page10 = "selected=true";
            $posts_per_page = 10;
            break;
        case '25':
            $posts_per_page25 = "selected=true";
            $posts_per_page = 25;
            break;
        case '50':
            $posts_per_page50 = "selected=true";
            $posts_per_page = 50;
            break;
}


global $wpdb;

$query = 

("SELECT $wpdb->posts.* 
    FROM $wpdb->posts, $wpdb->postmeta
        LEFT JOIN $wpdb->postmeta AS postmeta1
            ON (postmeta1.post_id = $wpdb->posts.id)
        LEFT JOIN $wpdb->postmeta AS postmeta2
            ON (postmeta2.post_id = $wpdb->posts.id)
    WHERE $wpdb->posts.post_type = 'horse'
    AND (postmeta1.meta_key = „owner_id_num“
        AND postmeta1.meta_value = $user_id
    )
    AND (postmeta2.meta_key = „show_horse_profile“
        AND postmeta2.meta_value = 1
    )")
;

$total = $wpdb->get_var( "SELECT COUNT(1) FROM (${query}) AS combined_table" );
$items_per_page = $posts_per_page;
$page = isset( $_GET['cpage'] ) ? abs( (int) $_GET['cpage'] ) : 1;
$offset = ( $page * $items_per_page ) - $items_per_page;
$latestposts = $wpdb->get_results( $query . " LIMIT ${offset}, ${items_per_page}" );

foreach ($latestposts as $currentPost) {
 //get post content
}

$pag = paginate_links( array(
    'base' => add_query_arg( 'cpage', '%#%' ),
    'format' => '',

    'show_all'           => false,
    'end_size'           => 0,
    'mid_size'           => 2,
    'prev_next'          => true,
    'prev_text'          => __('< Pref'),
    'next_text'          => __('Next >'),
    'type'               => 'array',
    'add_args'           => false,
    'add_fragment'       => '',
    'before_page_number' => '',
    'after_page_number'  => '',
    'total' => ceil($total / $items_per_page),
    'current' => $page
));



if(is_array($pag)){
    $last = end($pag);
    $first = reset($pag);
}


$prev = "";
$next = "";


if (\strpos($last, 'Next >') !== false) {
    $next = $last;
}
if(\strpos($first, '< Pref') !== false){
    $prev = $first;
}



<div class="paginationMenu">
    <div class="paginationPre">
        <?php echo $prev;?>
    </div>
    <div class="paginationPostsPerPage">
        Pagination:<select name="ppp" onchange="this.form.submit();">
            <option <?php echo $posts_per_page10?> value="10">10</option>
            <option <?php echo $posts_per_page25?> value="25">25</option>
            <option <?php echo $posts_per_page50?> value="50">50</option>
        </select>
    </div>
    <div class="paginationNext">
        <?php echo $next?>
    </div>
</div>

编辑:我根据这个src更改了查询:

https://wordpress.stackexchange.com/questions/40322/query-multiple-meta-key-values

$query = "  
        SELECT $wpdb->posts.* 
        FROM $wpdb->posts, $wpdb->postmeta, $wpdb->postmeta AS mt1
        WHERE $wpdb->posts.ID = $wpdb->postmeta.post_id 

        AND $wpdb->postmeta.meta_key = 'key1'   
        AND $wpdb->postmeta.meta_value = 'value1'
        AND mt1.meta_key = 'key1'
        AND mt1.meta_value = 'value2'

        AND $wpdb->posts.post_status = 'publish' 
        AND $wpdb->posts.post_type = 'horse'
        ORDER BY $wpdb->posts.post_date DESC
        ";

【讨论】:

  • 谢谢!得到错误“['on Clause'中的未知列'wp_posts.ID']”:/附加了我在第一篇文章中尝试的新查询。
  • @Heidi 我添加了一个更改 => 编辑:....也许您可以修复错误。我只尝试了使用单个 meta_key 和 meta_value 的代码,并且根据我发布的链接,我尝试将其更改为多个值。希望这对您有所帮助。
  • @Heidi 请在 Kalti 编辑查询时重新检查。它对你有用吗?如果查询对您有效,请检查查询时间,结果应与默认的 WordPress 查询相同。如果两者都很好,那么只进行其他更改而不是一次。
  • 谢谢你们。尝试了新版本。现在我没有收到错误,但看起来查询进入了无限循环,页面加载和加载并且永远不会完成。我现在将我当前的查询添加到我的第一篇文章中。
猜你喜欢
  • 2020-03-18
  • 1970-01-01
  • 1970-01-01
  • 2015-04-09
  • 1970-01-01
  • 2018-04-17
  • 2020-10-08
  • 1970-01-01
  • 2010-10-22
相关资源
最近更新 更多