您的原始代码(上一个问题中的代码)在给定的上下文中确实需要一些性能提升。对于更新的代码,您需要删除fields
参数,因为您需要获取完整的post对象,而不仅仅是ID。
要优化查询中的代码,您需要事先知道您需要从帖子中获得什么。我将用你上面的两个例子来解释。
在此之前,请快速执行以下操作:(这将有助于理解我想说的内容)
创建页面模板,并使用该模板创建新页面并在模板中添加以下行
timer_start();
// We will add our queries here
echo get_num_queries(); . \' queries in \' . timer_stop(1, 5); . \' seconds.\';
加载页面并记录查询量。您需要从计时器之间运行的所有查询中减去此数字
一旦有了基准测试,请分别添加以下两个查询来代替// We will add our queries here
并注意运行查询所需的时间差异。(这是测试查询及其效率的好方法)
(1)
$q = get_posts( \'post_type=advert&posts_per_page=-1\' );
var_dump( $q );
()
$q = get_posts( \'post_type=advert&posts_per_page=-1&fields=ids\' );
var_dump( $q );
另请注意,不要使用全局变量(
$posts
和$post
)作为局部变量,这会打断全局变量并给出意外的输出。这种情况很难调试。使用唯一且不在全局变量范围内的局部变量。唯一必须用作局部变量的全局变量是
$post
将postdata设置为
setup_postdata( $post )
期望
$post
全球的完成后请记住重置它
wp_reset_postdata()
.
代码块1在第一个代码块的上下文中,查询所需的全部是post IDwp_update_post()
只需要post ID。如果查看源代码,wp_update_post()
进行自己的调用,以获取完整的post对象与传递给它的数组合并。
代码所做的是检索完整的post对象,从中获取ID,并将其传递给wp_update_post()
然后wp_update_post()
再次调用以从ID获取完整的post对象。这既昂贵又不必要,就像两次吃同一块肉一样。
您必须记住,即使帖子被缓存到缓存中,获取相关数据仍然需要时间,而且获取的数据越多,所需时间就越长。这就是\'fields\'=>\'ids\'
很方便,因为它将检索一个post ID数组,而不是post对象数组(请检查我要求您测试的测试数据)。一切正常,只是循环略有不同,因为您的帖子是作为ID而不是对象返回的
代码块一可以是这样的
add_action( \'adverts_event_expire_ads\', \'adverts_event_expire_ads\' );
/**
* Expires ads
*
* Function finds Adverts that already expired (value in _expiration_date
* meta field is lower then current timestamp) and changes their status to \'expired\'.
*
* @since 0.1
* @return void
*/
function adverts_event_expire_ads() {
// find adverts with status \'publish\' which exceeded expiration date
// (_expiration_date is a timestamp)
$q = new WP_Query( array(
"fields" => "ids", //added for performance
"post_type" => "advert",
"post_status" => "publish",
"meta_query" => array(
array(
"key" => "_expiration_date",
"value" => current_time( \'timestamp\' ),
"compare" => "<="
)
)
) );
if( $q->post_count ) {
foreach($q->posts as $post_id) {
// NOTE: $q->posts are an array of post ID\'s, so $post_id is a post ID
// change post status to expired.
$update = wp_update_post( array(
"ID" => $post_id,
"post_status" => "expired"
) );
} // endforeach
} // endif
}
代码块2在上下文中,可以删除
\'fields\'=>\'ids\'
在这里两个原因
你需要帖子的作者和标题等信息,而不仅仅是帖子ID。如果你需要帖子ID以外的其他信息,你别无选择,只能获取完整的帖子对象。你可以试试posts_fields
过滤器只返回某些字段,但在测试中,这并没有产生任何明显的差异。另请注意,此筛选器未打开get_posts()
默认情况下
您正在使用get_post()
从post ID获取post数据。如果post在post缓存中,这不会创建额外的db查询,但获取post对象确实需要额外的时间。这一切都是不必要的。最好从一开始就获得完整的post对象
因此,您可以在代码块2中重写函数,如下所示:
remove_action( \'adverts_event_expire_ads\', \'adverts_event_expire_ads\' );
add_action( \'adverts_event_expire_ads\', \'my_adverts_event_expire_ads\' );
/**
* Expires ads
*
* Function finds Adverts that already expired (value in _expiration_date
* meta field is lower then current timestamp) and changes their status to \'expired\'.
*
* @since 0.1
* @return void
*/
function my_adverts_event_expire_ads() {
// Set our query arguments
$args = [
\'post_type\' => \'advert\',
\'post_status\' => \'publish\',
\'meta_query\' => [
[
\'key\' => \'_expiration_date\',
\'value\' => current_time( \'timestamp\' ),
\'compare\' => \'<=\'
]
]
];
// get adverts with status \'publish\' which exceeded expiration date
// (_expiration_date is a timestamp)
$q = get_posts( $args );
// Check if we have adverts with exceeded expiration date, if not, return false
if ( !$q )
return;
// If we have posts with exceeded expiration time, lets change their status to expired
foreach($q as $post_object) {
// $post_object is now an object of post data
// change post status to expired.
$update = wp_update_post( array(
"ID" => $post_object->ID,
"post_status" => "expired"
) );
// Send an email about expiration to the post author
$author = get_userdata($post_object->post_author);
$author_name = get_post_meta( $post_object->ID, \'adverts_person\', true );
$message =
"Hi " . $author_name . ", " .
"\\n\\nYour advert, \\"" . $post_object->post_title . "\\", expired and will be deleted in 7 days." .
"\\n\\nBest regards, \\n\\"" . get_bloginfo() . "\\" team";
wp_mail($author->user_email, "Your article expired!", $message);
} // endforeach
}
额外注意事项:正如我所说,在优化查询之前,您需要知道您需要从查询中获得什么。
在使用函数之前,请确保您了解其内部工作原理。例如,get_category_link()
接受类别ID或类别对象作为参数。使用这两个选项中错误的一个会对性能产生巨大影响,特别是如果你有很多类别的话。当您传递ID时,函数将进行db调用,以获取category对象来构建链接。如果传递该对象,则该对象将按原样用于构建链接,因此不会执行db调用。
developer.wordpress.org
是一种查找函数及其源代码的好方法,因此请将此地址添加到书签中并加以滥用
使用cache parameters in WP_Query
如果您不需要缓存术语和自定义字段数据,还可以提高性能,从而实现术语和自定义字段数据的缓存。
使用我给您的小测试脚本来测试查询和自定义代码。这样,您将知道代码将如何执行。另外,下载并安装一个插件,如Query Monitor 和Debug Objects 在本地测试安装上。这将分解查询,以便您可以检查每个查询,并检查其实际效率。它还有助于调试。我个人认为每个人都应该在他们的测试装置上安装这两个冥王星