如何为数以百万计的帖子优化WP网站


19

我正在一家公司的网站上工作,该公司很可能会通过自定义帖子类型创建数百万个帖子。他们是祈祷,所以基本上前端的用户只是通过表单提交了一个简短的短语。公司所关心的只是帖子内容和发布日期。该网站甚至还没有启动,他们已经有超过120,000个帖子,所以当我说几百万时,我非常认真。

因此,有几个优化问题:

  1. 假设我在具有500,000个帖子的自定义帖子类型中有一个“精选”类别。特色类别只有500个帖子。如果我为特色帖子创建查询,是查询整个500,000个帖子,还是仅查询500个特色帖子?如果我只想显示精选的十篇最新文章怎么办?
  2. 将这种自定义帖子类型保存到数据库时,我可以做些什么来减少服务器资源,特别是因为真正需要的只是帖子的内容和日期?
  3. 我是否应该使用自定义帖子类型?我原则上喜欢它,因为它已很好地集成到WordPress管理员中,但是如果性能存在明显的劣势,那么我想我可以做一些不同的事情。

我从未在如此规模的项目上工作过,所以我比平时更关心性能。谢谢你的帮助!


在WordPress函数中尽量减少数据库查询并适当地调用脚本,这一点很重要,但是优化的很大一部分与服务器的设置和配置有关。为此,请搜索“服务器故障”网络。serverfault.com/search?q=optimize+wordpress
iyrin 2014年

@RyanLoremIpsum-感谢您的评论,但我希望为我的具体问题提供答案。我在那里找到的大部分内容都与服务器本身有关,而不是WordPress的工作方式以及如何从代码角度优化服务器
Jeremiah Prummer 2014年

Answers:


26

1. 运行WP_Query 之前设置查询

尝试将数据库查询减至最少时,这似乎是要记住的最重要的事情,因为更改查询的唯一机会当然是在SQL数据库中运行之前。

普通查询
对于普通查询,WordPress使用此wp()函数,该函数依次调用$wp->main( $query_vars )。在将条件标签的“ is_变量”传递给之前,先对其进行设置WP_Query->get_posts(),然后将其转换为MySQL数据库查询,最后将其存储在$ wp_query对象中。可以在SQL数据库中实际运行查询之前对其进行过滤。

pre_get_posts操作与该过程相关,可让您在将查询传递给之前对其进行更改WP_Query->get_posts()

例如,如果您要过滤查询“特色”类别中的帖子,则可以在中使用条件标记add_action( 'pre_get_posts', 'your_function_name' );并将其包括in_category在内your_function_name

function your_function_name( $query ) {
    if ( $query->in_category( 'featured' ) && $query->is_main_query() ) {
        // Replace 123 with the category ID of the featured category.
        $query->set( 'cat', '123' );
    }
}
add_action( 'pre_get_posts', 'your_function_name' );

请参阅插件API /操作参考/获取相关职位«WordPress Codex

页面请求
至于页面模板,例如“功能”类别的存档页面,条件标签将无法从pre_get_posts过滤器中使用。例如,您不能使用is_category来检查存档页面,因为WP_Query尚未运行。

相反,您必须使用来更改页面请求的主查询,new WP_Query其外观类似于$query = new WP_Query( 'cat=123' );。这将从一开始就使用适当的参数集运行查询。

请参阅类参考/ WP查询«WordPress Codex

2.保存到数据库

您可以使用过滤器,wp_insert_post_data确保仅将与自定义帖子类型相关的$ data返回给wp_insert_post。确保包含条件语句以检查您的自定义帖子类型。
插件API /过滤器参考/ WP插入帖子数据«WordPress Codex

该钩子由wp_insert_post函数调用,该函数在您更新自定义帖子类型时通常由保存草稿或发布帖子来由wp_update_post调用。

不过,您必须自己对其进行基准测试,因为我个人无法谈到减少数据库中更新数据的优化意义。

3.自定义帖子类型会影响性能吗?

以我的经验,自定义帖子类型是用于管理内容的强大工具。我不知道有什么其他方式可以使用较少的资源来以允许的所有方式来管理帖子。我个人将重点放在寻找方法上,以尽可能减少查询的数量。

以前存在与永久链接结构相关的性能问题,导致其以文本开头而不是数字开头时会受到打击。3这对于承载大量页面的网站特别麻烦,但自WordPress 3.3版以来已解决。

我只在这里提到永久链接,因为该段通常是永久链接结构的第一部分,在3.3版本之前,它可能会或可能不会影响性能。除此之外,我不知道使用自定义帖子类型会引起任何性能问题。

其他性能选项

瞬态
这不是将代码中的查询保持在最少数量的替代方法,但是您可以使用set_transient将查询存储一段时间,这样就不需要新的查询了。这是Dave Clements帖子中使用的示例。另外,请注意,他建议save_post在给定帖子类型更新后立即添加操作以删除瞬态。

<?php // IN THE SPOTLIGHT QUERY
if( false === ( $its_query = get_transient( 'its_query' ) ) ) {
    $pttimestamp = time() + get_option('gmt_offset') * 60*60;
    $its_query = new WP_Query( array(
        'post_type' => 'spotlight',
        'posts_per_page' => 1,
            'post__not_in' => $do_not_duplicate,
        'meta_query' => array(
            array(
                'key' => '_hpc_spotlight_end_time',
                'value' => $pttimestamp,
                'compare' => '>'
            )
        )
    ) );
    set_transient( 'its_query', $its_query, 60*60*4 );
}
if( have_posts() ) { // HIDE SECTION IF NO CURRENT ITS FEATURE ?>
    // LOOP GOES HERE: NOT IMPORTANT TO EXAMPLE
<?php } ?>

更多查询优化
Thomas Griffin在他的Optimize WordPress Queries教程中有一些不错的技巧。以下是他的建议的简要列表:

  • 'cache_results' => false如果您的服务器未使用持久性缓存(例如Memcached),请设置一次查询。一次性查询被描述为“用于显示少量数据的查询。可能是您只想显示与当前帖子相关的链接帖子标题,或者您可能想显示一个下拉列表来选择特定的选项设置。”

    他的例子: $query = get_posts( array( 'posts_per_page' => 1, 'cache_results' => false ) );

  • 设置'no_found_rows' => true不需要分页的位置。这将“绕过MySQL计算结果以查看是否需要分页”。

    他的例子: $query = new WP_Query( array( 'posts_per_page' => 1, 'no_found_rows' => true ) );

  • 对于后期的ID只查询,如果这是你需要'fields' => 'ids'get_posts。这将显着减少返回的数据量,如果您查看数据库描述,则每个帖子的数量很多 «WordPress Codex

    他的例子: $query = get_posts( array( 'posts_per_page' => 1, 'fields' => 'ids' ) );

除了最后一个技巧外,当您只需要使用get_post_field一个或几个post字段时,可以应用相同的推理。

扎实的了解查询的工作原理至关重要。查询越具体,对SQL数据库的要求就越少。这意味着管理数据库查询有很多可能性。在自定义查询的运行位置(这是一个管理页面?)要小心,在直接查询中使用适当的清理方法,并尝试使用本机WordPress函数来实现相同的性能。


2
出色且极有帮助的答案,谢谢!
Jeremiah Prummer,2014年

该主题是完全定制的,因此我们只查询绝对必要的项目。这些都是非常有帮助的。鉴于此,我将回顾并对查询进行一些更改。;)
Jeremiah Prummer 2014年

1
我要补充一点,您应尽可能避免元查询。当然,不要同时对两个元字段运行查询。这导致重复查询和三次查询,从而迅速成为性能问题。自定义帖子类型通常可以对此提供帮助。
查尔斯·贾梅特

3

我还添加:

    'no_found_rows'          => true,
    'update_post_term_cache' => false,
    'update_post_meta_cache' => false,
    'cache_results'          => false
  • no_found_rows(布尔值)–当您不需要任何分页并且不需要对找到的帖子总数进行计数时,请设为true。
  • cache_results(布尔值)–发布信息缓存。
  • update_post_meta_cache(布尔值)–发布元信息缓存。
  • update_post_term_cache(布尔值)–术语后信息缓存。

通过使用这些参数并将值作为FALSE传递,我们可以通过停止执行一些额外的数据库查询来加快查询速度。

注意:我们不应该总是使用这些参数,因为将事情添加到缓存是正确的做法,但是在特定情况下它们可能很有用,并且您应该在知道自己正在做什么时考虑使用。

请访问:https//drujoopress.wordpress.com/2013/06/27/how-to-optimize-wordpress-query-to-get-results-faster/#more-184


1
编辑您的答案,并添加解释:为什么这可以解决问题?
fuxia

我无法对这个答案发表评论:wordpress.stackexchange.com/a/166699/57674
rigosan

1

由于所有过早的优化类型的问题,如果不知道确切的使用模式(只有在上线时才会被发现太多次),就无法真正回答该问题。

通常,根据MYSQL规范,数据量应该没有任何问题。当然,即使使用最佳算法搜索数据也要比使用较小的表慢一些,但是解决方案是简单而强大的CPU。

您可能想优化元数据的存储方式(例如,不存储与ping相关的数据),但是这种事情取决于您的工作方式,最终您可能仍需要更强大的CPU,因此可能不值得您付出麻烦。

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.