Description
I meet a different performance issues with your great plugin P2P :
My database :
- 33 000 posts rows
- 47 000 p2p relations rows
- 20 000 users rows
My current SQL version : 5.5.27-1~dotdeb.0
SQL queries takes an incredible time (9.0331 sec) with this kind of queries :
When i display a list of custom post type :
http://mywebsite/wp-admin/edit.php?post_type=my_cpt
SELECT wpasc_posts.*, wpasc_p2p.* FROM wpasc_posts INNER JOIN wpasc_p2p WHERE 1=1 AND wpasc_posts.post_type IN ('adherent') AND (wpasc_posts.post_status = 'publish' OR wpasc_posts.post_status = 'future' OR wpasc_posts.post_status = 'draft' OR wpasc_posts.post_status = 'pending' OR wpasc_posts.post_author = 96258 AND wpasc_posts.post_status = 'private') AND (wpasc_p2p.p2p_type = 'member_to_member' AND (
(wpasc_posts.ID = wpasc_p2p.p2p_to AND wpasc_p2p.p2p_from IN (SELECT wpasc_posts.ID FROM wpasc_posts WHERE 1=1 AND wpasc_posts.ID IN (120513,120510,96094,96095,96156,96268,96269,96267,96291,96292,96332,96333,96406,96420,96551,96552,96573,96574,96572,96607) AND wpasc_posts.post_type IN ('adherent') AND (wpasc_posts.post_status = 'publish' OR wpasc_posts.post_status = 'future' OR wpasc_posts.post_status = 'draft' OR wpasc_posts.post_status = 'pending' OR wpasc_posts.post_author = 96258 AND wpasc_posts.post_status = 'private') ORDER BY wpasc_posts.post_date DESC )) OR
(wpasc_posts.ID = wpasc_p2p.p2p_from AND wpasc_p2p.p2p_to IN (SELECT wpasc_posts.ID FROM wpasc_posts WHERE 1=1 AND wpasc_posts.ID IN (120513,120510,96094,96095,96156,96268,96269,96267,96291,96292,96332,96333,96406,96420,96551,96552,96573,96574,96572,96607) AND wpasc_posts.post_type IN ('adherent') AND (wpasc_posts.post_status = 'publish' OR wpasc_posts.post_status = 'future' OR wpasc_posts.post_status = 'draft' OR wpasc_posts.post_status = 'pending' OR wpasc_posts.post_author = 96258 AND wpasc_posts.post_status = 'private') ORDER BY wpasc_posts.post_date DESC ))
)) ORDER BY wpasc_posts.post_date DESC
Explain results give :
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY wpasc_posts ref PRIMARY,type_status_date,post_author type_status_date 62 const 18712 Using where; Using temporary; Using filesort
1 PRIMARY wpasc_p2p ALL p2p_from,p2p_to,p2p_type NULL NULL NULL 47583 Using where; Using join buffer
3 DEPENDENT SUBQUERY wpasc_posts unique_subquery PRIMARY,type_status_date,post_author PRIMARY 8 func 1 Using where
2 DEPENDENT SUBQUERY wpasc_posts unique_subquery PRIMARY,type_status_date,post_author PRIMARY 8 func 1 Using where
The first problem is that the request is never cached by MySQL (because too large I think)
I made a plugin to simplify the SQL query and finally allow the splitting introduced in WP 3.4. (first get IDS, after get contents with ID
The plugin :
<?php
/*
Plugin Name: Speedup P2P
Plugin URI: http://www.beapi.fr
Description: Change query from P2P plugin, for get ID instead ALL data (*) for posts, make 2 queries instead once !
Author: BeAPI
Author URI: http://www.beapi.fr
Version: 0.1
----
Copyright 2012 Amaury Balmer (amaury@beapi.fr)
----
*/
class Speedup_P2P {
function __construct() {
add_filter('posts_request', array(&$this, 'posts_request'), 9999999, 2 );
add_filter('posts_results', array(&$this, 'posts_results'), 1, 2 );
}
function posts_request( $request, $query ) {
global $wpdb;
$new_request = $request;
$new_request = str_replace("SELECT SQL_CALC_FOUND_ROWS $wpdb->posts.*, $wpdb->p2p.* FROM", "SELECT SQL_CALC_FOUND_ROWS $wpdb->posts.ID, $wpdb->p2p.* FROM", $new_request);
$new_request = str_replace("SELECT $wpdb->posts.*, $wpdb->p2p.* FROM", "SELECT $wpdb->posts.ID, $wpdb->p2p.* FROM", $new_request);
if ( $new_request != $request ) {
$query->p2p_flag = true;
}
return $new_request;
}
function posts_results( $posts, $query ) {
global $wpdb;
if ( isset($query->p2p_flag) && $query->p2p_flag == true && !empty($posts) ) {
// Restore flag
$query->p2p_flag = false;
// Get posts IDs for get contents
$_posts = array();
foreach( $posts as $post ) {
$_posts[] = $post->ID;
}
// setup posts data
_prime_post_caches( $_posts, $query->query_vars['update_post_term_cache'], $query->query_vars['update_post_meta_cache'] );
$_posts = array_map( 'get_post', $_posts );
// Put ID on key
foreach( $_posts as $key => $_post ) {
unset($_posts[$key]);
$_posts[$_post->ID] = $_post;
}
// Merge datas
$query->posts = array();
foreach( $posts as $post ) {
$query->posts[] = (object) array_merge((array) $_posts[$post->ID], (array) $post);
}
return $query->posts;
}
return $posts;
}
}
add_action( 'plugins_loaded', create_function('', 'return new Speedup_P2P();') );
The new query :
SELECT wpasc_posts.ID, wpasc_p2p.* FROM wpasc_posts INNER JOIN wpasc_p2p WHERE 1=1 AND wpasc_posts.post_type IN ('adherent') AND (wpasc_posts.post_status = 'publish' OR wpasc_posts.post_status = 'future' OR wpasc_posts.post_status = 'draft' OR wpasc_posts.post_status = 'pending' OR wpasc_posts.post_author = 96258 AND wpasc_posts.post_status = 'private') AND (wpasc_p2p.p2p_type = 'member_to_member' AND (
(wpasc_posts.ID = wpasc_p2p.p2p_to AND wpasc_p2p.p2p_from IN (SELECT wpasc_posts.ID FROM wpasc_posts WHERE 1=1 AND wpasc_posts.ID IN (120513,120510,96094,96095,96156,96268,96269,96267,96291,96292,96332,96333,96406,96420,96551,96552,96573,96574,96572,96607) AND wpasc_posts.post_type IN ('adherent') AND (wpasc_posts.post_status = 'publish' OR wpasc_posts.post_status = 'future' OR wpasc_posts.post_status = 'draft' OR wpasc_posts.post_status = 'pending' OR wpasc_posts.post_author = 96258 AND wpasc_posts.post_status = 'private') ORDER BY wpasc_posts.post_date DESC )) OR
(wpasc_posts.ID = wpasc_p2p.p2p_from AND wpasc_p2p.p2p_to IN (SELECT wpasc_posts.ID FROM wpasc_posts WHERE 1=1 AND wpasc_posts.ID IN (120513,120510,96094,96095,96156,96268,96269,96267,96291,96292,96332,96333,96406,96420,96551,96552,96573,96574,96572,96607) AND wpasc_posts.post_type IN ('adherent') AND (wpasc_posts.post_status = 'publish' OR wpasc_posts.post_status = 'future' OR wpasc_posts.post_status = 'draft' OR wpasc_posts.post_status = 'pending' OR wpasc_posts.post_author = 96258 AND wpasc_posts.post_status = 'private') ORDER BY wpasc_posts.post_date DESC ))
)) ORDER BY wpasc_posts.post_date DESC
The results of this query are allowed in the cache MySQL queries but are still slow. (1 to 2 seconds)
How can we improve the performance of P2P in a large database? there's there any specific settings to include for mysql?