ちょっと嬉しい発見があったのでメモ。
余分にSQLを発行することでトータルのDBコール回数を劇的に減らせることがある
たとえば次のように10通の投稿へのリンクを作ると、SQLは20回発行される。
// 表示したい投稿ID
$post_ids = array( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 );
// 各投稿へのリンクを作成
foreach ( $post_ids as $post_id ) {
    $out[] = sprintf(
        '<li><a href="%s">%s</a></li>',
        get_permalink( $post_id ),
        get_the_title( $post_id ),
    );
}これは get_permalink() が内部的に get_post() を発行するため。get_post() は投稿と関連タームを取得するためにDBを2回コールする。get_the_title()  はオブジェクトキャッシュからデータを取得するのでDBアクセスは発生しない。
このとき次のように get_permalink()  の前にまとめて投稿を取得しておくと、発行される回数は2回で済む。投稿を取得するための1回と、関連タームを取得するための1回。
$post_ids = array( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 );
$q = new WP_Query( array(
    'post_status'            => 'publish',
    'post__in'               => $post_ids,
    'posts_per_page'         => -1,
    'update_post_meta_cache' => false,
) );
unset( $q );
foreach ( $post_ids as $post_id ) {
    $out[] = sprintf(
        '<li><a href="%s">%s</a></li>',
        get_permalink( $post_id ),
        get_the_title( $post_id ),
    );
}取得してすぐ unset() しているので無駄なようだが、DBコールの数を大きく削減する効果がある。
これは、WP_Queryが取得した投稿を個別にキャッシュしてくれているため。取得するだけで効果があることを示すために unset() を入れたが、放置でもOK。
ソースをたどってみると、次のような流れで投稿を個別にキャッシュに格納していた。なんとなく、まとめて取得したデータはまとめてキャッシュされるかと思っていたけれど、当然ながらこのほうがヒット率が高い。
new WP_Query()
   → __construct()
      → get_post()
         → update_post_caches()
            → update_post_cache()
               → 投稿を個別に wp_cache_add()なお 'update_post_meta_cache' => false は、ついでに投稿メタを取得しておくためのSQL発行を抑制する。SQL1回だけだが節約にはなる。
 'update_post_term_cache' => false を加えてしまうと逆効果。get_the_category() のなかでタームを取得しているため。ただしパーマリンクの構造によっては
なんにせよget_permalink()にかぎらず、このテクニックは覚えておきたい。