Durante el tiempo que no hubo actividad alguna en este blog y por algunos trabajos que me encomendaron relacionados al desarrollo de plugins y modificación del código de WordPress, he visto algo que se repite casi en todos los plugins que he visto hasta el momento: usan varias consultas pequeñas cuando sólo una puede hacer el trabajo (no tengo idea de porqué hacen las cosas de ese modo).
php:
$a = query
("select ID from tabla1 ...");
$b = 
array();
foreach($a as $v) {
        $b[] = query
("select ... from tabla2 where ID = $v");
} 
 
El problema del código mostrado es que se hacen consultas innecesarias a la base de datos cuando en este caso un simple JOIN serviría para el mismo propósito.
Como ejemplo voy a poner dos plugins que acompañaron a este blog desde hace más de un año y por los que el número de consultas SQL aunmentaba en 55 para generar la página principa. Éstos son:
- 
Real Fast Latest Comments: En este caso el plugin realiza una consulta para obtener las entradas que recibieron comentarios recientemente y luego itera para mostrar los datos devueltos:
php:
function rflc_show_comments
($comment_limit = 
5, 
$show_trackbacks = 
false) {
        global $wpdb;
        if(!$show_trackbacks) {
                $activity = $wpdb->get_results("SELECT $wpdb->comments.comment_date, $wpdb->comments.comment_author, 
                                                $wpdb->comments.comment_ID, $wpdb->posts.post_title, 
                                                $wpdb->posts.ID FROM $wpdb->comments INNER JOIN 
                                                $wpdb->posts ON $wpdb->posts.ID = $wpdb->comments.comment_post_ID WHERE 
                                                $wpdb->comments.comment_approved = '1' AND $wpdb->comments.comment_type 
                                                NOT LIKE '%back%' ORDER BY $wpdb->comments.comment_date DESC
                                                LIMIT $comment_limit");
        } else {
                $activity = $wpdb->get_results("SELECT $wpdb->comments.comment_date, $wpdb->comments.comment_author, 
                                                $wpdb->comments.comment_ID, $wpdb->posts.post_title, 
                                                $wpdb->posts.ID FROM $wpdb->comments INNER JOIN 
                                                $wpdb->posts ON $wpdb->posts.ID = $wpdb->comments.comment_post_ID WHERE 
                                                $wpdb->comments.comment_approved = '1' 
                                                ORDER BY $wpdb->comments.comment_date DESC
                                                LIMIT $comment_limit");
        }
        
        if($activity) {
                echo '<ul>';
                foreach($activity as $comment) {
                        echo '<li>'.wp_specialchars
($comment->
comment_author).
' en: <a href="'. get_permalink
($comment->
ID) .
'#comment-'. 
$comment->
comment_ID .
'">'. wp_specialchars
($comment->
post_title) .
'</a></li>' . 
"\n";
 
                }
                echo '</ul>';
        }
}
 
 
El problema en este caso es que para mostrar el enlace (permalink) de una entrada, el plugin invoca en cada iteración a la función get_permalink, la misma que hace una nueva consulta (o varias dependiendo de la estructura de permalinks) para recuperar la entrada y formatear el enlace, esto pasa siempre y cuando el argumento pasado no sea un objeto o la entrada ya se encuentre en la caché de objetos.
 
- 
Related Posts: El problema es el mismo que se comenta en el anterior, a continuación muestro la parte relevante:
php:
$sql = 
"SELECT ID, post_title, post_content,"
         . 
"MATCH (post_name, post_content) "
         . 
"AGAINST ('$terms') AS score "
         . 
"FROM $wpdb->posts WHERE "
         . 
"MATCH (post_name, post_content) "
         . 
"AGAINST ('$terms') "
         . 
"AND post_date <= '$now' "
         . 
"AND (post_status IN ( 'publish',  'static' ) && ID != '$post->ID') ";
if ($show_pass_post==
'false') { $sql .= 
"AND post_password ='' "; 
}
$sql .= 
"ORDER BY score DESC LIMIT $limit";
$results = 
$wpdb->
get_results($sql);
$output = 
'';
if ($results) {
        foreach ($results as $result) {
                $title = 
stripslashes(apply_filters
('the_title', 
$result->
post_title));
                $permalink = get_permalink($result->ID);
                $post_content = strip_tags($result->post_content);
                $post_content = stripslashes($post_content);
                $output .= $before_title .'<a href="'. $permalink .'" rel="bookmark" title="Permanent Link: ' . $title . '">' . $title . '</a>' . $after_title;
                if ($show_excerpt=='true') {
                        $words=split(" ",$post_content); 
                        $post_strip = join(" ", array_slice($words,0,$len));
                        $output .= $before_post . $post_strip . $after_post;
                }
        }
        echo $output;
}
 
 
 
Para evitar este comportamiento pero con algunas posibles consecuencias no deseadas**, se debe recuperar también el campo post_name en la primera consulta de ambos casos y a continuación invocar a la función get_permalink con un objeto como parámetro -- get_permalink($comment); y get_permalink($result); respectivamente.
**: Al usar la función get_permalink con un objeto como parámetro, éste se almacena en el caché de objetos y cualquier función que haga uso de get_post puede mostrar entradas "incompletas". Una forma de evitar esto es recuperar todos los campos de la tabla posts o quitar la entrada almacenada en cache luego de invocar a la función get_permalink.