Nucleus

SQLクエリのキャッシュ:実験失敗

2008年12月25日

失敗した実験も記録しておかないと、あとでまた同じ事を試そうとするかもしれないので…。

Jeansのコードを書いているときに、Nucleusのコアのコードを眺めることがあるのだが、ふと思ったことは、同じSQLクエリーを繰り返し実行しているのではないかということ。これは正直、無駄である。なので、SQLクエリーをキャッシュして、再利用できないかを探ってみた。

Nucleusの場合、クエリーはglobalfunctions.phpにあるグローバル関数、sql_query()で行われている。次のようなコードだ。

function sql_query($query) {
    global $SQLCount;
    $SQLCount++;
    $res = mysql_query($query) or print("mySQL error with query $query: " . mysql_error() . '<p />');
    return $res;
}

これを、以下のように変更してみた。

function sql_query($query) {
    static $cache=array();
    if (isset($cache[$query])) {
        $res=$cache[$query];
        if (@mysql_data_seek($res,0)) return $res;
        else unset($cache[$query]);
    }
    global $SQLCount;
    $SQLCount++;
    $res = mysql_query($query) or print("mySQL error with query $query: " . mysql_error() . '<p />');
    if (mysql_num_rows($res)<5) $cache[$query]=$res;
    return $res;
}

リソースを、キャッシュとしてスタティック変数に残しておいて、同じクエリーが実行する場合は巻き戻して再利用しようというもの。もちろん、データベースに変更が加えられたときなどは同じクエリーでも結果が異なる。しかしながら、それについては後でコードを書き換えて対応することにして、とりあえず上記コードで実験してみた。

まず、Nucleusインストール直後のデフォルト状態で、クエリー実行回数が一回減ることを確認。気をよくして、このブログに試しに入れてみた結果……。クエリー実行回数は減らなかった。

Nucleusのクエリーの実行回数の多さは異常ともいえるほどなので、ゆくゆくは何か対処したい。Jeansでは、何らかのキャッシュ機構を是非導入したいと考えている。こういった仕組みについては、hsurさんのCACHEMANAGERがあるけれど、少し違った考え方で導入することを考えている。忘れないうちにアイデアだけここにメモしておくと、ようするにキャッシュ用のテーブルを一つ用意し、スキンパース前にそれらの内容を一気に取り込んでしまおうという物。テンポラリテーブルだとかの機能を利用することになりそう。fetchのさいにオブジェクトを利用しているJeansの方が、実装は容易かもしれない。

コメント

Andy (2008年12月25日 17:18:03)

クエリーの回数を減らすにはロー・レベルのチューニングよりもハイ・レベルの方が効くと思っています。
例えば,アイテムを取得するときに,そのアイテムのプラグイン・オプションを同時に取得するとか,アイテム・オブジェクトは1回読み込んだら次回以降はDBアクセスに行かず,メモリー内のオブジェクトを利用するとか。テンプレート・パーツをパーツごとに取りに行くのでなく,一括して取得しておくとか。

Kat (2008年12月25日 18:23:36)

そうですね、そのあたりは考えていて、Jeansではいくらか実装しています。例えば、プラグインオプションのケースでは、一度のクエリーですべてのオプションのデータを読み込むようにしています。

これを参考に決めています。
http://www.recfor.net/blog/jeans/index.php?itemid=552

そういった工夫をした上で、さらにキャッシュできないかなと考えています。極端なケースですが、一回のアクセスに一度のクエリー発行だけですべてのデータを用意できるようなができればというところです。

もっとも、クエリーのキャッシュよりも、ページ全体のキャッシュの方が効率が良いようなケースもあると思いますが。あくまで、アイデアだけ暖めておこうという趣旨ですね。

コメント送信