我试图在幻灯片中添加基于2个不同键的2种幻灯片,只是元查询非常慢。我正在使用的wordpress查询是:
$args = array(
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'sgt_slide',
'value' => 'on',
'compare' => '='
),
array(
'key' => 'sgt_slide_home',
'value' => 'on',
'compare' => '='
)
),
'no_found_rows' => true, //exclude unnecessary paging calculations
'numberposts' => -1,
'post_status' => array( 'publish', 'inherit' ),
'post_type' => array( 'post', 'attachment' )
);
$slides = get_posts($args);
和结果的SQL匹配查询
SELECT nd_posts.* FROM nd_posts INNER JOIN nd_postmeta ON (nd_posts.ID = nd_postmeta.post_id)
INNER JOIN nd_postmeta AS mt1 ON (nd_posts.ID = mt1.post_id) WHERE 1=1 AND nd_posts.post_type IN ('post', 'attachment') AND ((nd_posts.post_status = 'publish' OR nd_posts.post_status = 'inherit')) AND ( (nd_postmeta.meta_key = 'sgt_slide' AND CAST(nd_postmeta.meta_value AS CHAR) = 'on')
OR (mt1.meta_key = 'sgt_slide_home' AND CAST(mt1.meta_value AS CHAR) = 'on') ) GROUP BY nd_posts.ID ORDER BY nd_posts.post_date DESC
此sql导致查询在7秒内加载,在phpmyadmin中测试。我怎么能克服这个。
EXPLAIN SQL
答案 0 :(得分:1)
尝试添加
'cache_results' => false,
到你的循环
答案 1 :(得分:1)
WordPress强制转换为char(),它会停止使用的索引。以下代码使用过滤器删除强制转换:
/**
* Remove casting a meta_query to a char as this stops it using the index!
*/
function my_filter_meta_query( $pieces ) {
if ( !empty( $pieces['where'] ) ) {
// remove casting to CHAR as this is already a string
$pieces['where'] = preg_replace("@CAST\(([^.]*.meta_value) AS CHAR\)@", "$1",$pieces['where']);
}
return $pieces;
}
add_filter( 'get_meta_sql', 'my_filter_meta_query' );
更多详情http://www.topsemtips.com/2015/01/wordpress-meta-query-slow-wp_query/
答案 2 :(得分:0)
很高兴基于此解决方法:https://wordpress.stackexchange.com/questions/158898/meta-query-terribly-slow
function wpse158898_posts_clauses( $pieces, $query ) {
global $wpdb;
$relation = isset( $query->meta_query->relation ) ? $query->meta_query->relation : 'AND';
if ( $relation != 'OR' ) return $pieces; // Only makes sense if OR.
$prepare_args = array();
$key_value_compares = array();
foreach ( $query->meta_query->queries as $meta_query ) {
// Doesn't work for IN, NOT IN, BETWEEN, NOT BETWEEN, NOT EXISTS.
if ( ! isset( $meta_query['value'] ) || is_array( $meta_query['value'] ) ) return $pieces; // Bail if no value or is array.
$key_value_compares[] = '(pm.meta_key = %s AND pm.meta_value ' . $meta_query['compare'] . ' %s)';
$prepare_args[] = $meta_query['key'];
$prepare_args[] = $meta_query['value'];
}
$sql = ' JOIN ' . $wpdb->postmeta . ' pm on pm.post_id = ' . $wpdb->posts . '.ID'
. ' AND (' . implode( ' ' . $relation . ' ', $key_value_compares ) . ')';
array_unshift( $prepare_args, $sql );
$pieces['join'] = call_user_func_array( array( $wpdb, 'prepare' ), $prepare_args );
$pieces['where'] = preg_replace( '/ AND[^' . $wpdb->postmeta[0] . ']+' . $wpdb->postmeta . '.*$/s', '', $pieces['where'] ); // Zap postmeta clauses.
return $pieces;
}
add_filter( 'posts_clauses', 'wpse158898_posts_clauses', 10, 2 );
$slidess = new WP_Query($args);
$slides = $slidess->get_posts();
remove_filter( 'posts_clauses', 'wpse158898_posts_clauses', 10 );
并设法使用新的get_posts
和WP_query
函数模仿get_posts()
的相同模式。