0

Zend_Cache_CoreとZend_Cache_Backend_Fileを使用して、データベースにアクセスするモデルクラスに対して実行されたクエリの結果をキャッシュしています。

基本的に、クエリ自体は、取得した結果をキャッシュするためのIDを形成する必要がありますが、問題は、クエリが長すぎることだけです。Zend_Cache_Backend_Fileは例外をスローせず、PHPは文句を言いませんが、キャッシュファイルは作成されません。

私はまったく効率的ではない解決策を考え出しました。実行されたクエリを自動インクリメントIDと一緒に、次のような別のファイルに保存します。

0->> SELECT*FROMテーブル1->>SELECT* FROM table1、table2 2->> SELECT*FROMテーブルWHEREfoo= bar

あなたはその考えを理解します。このように、私はすべてのクエリに対して一意のIDを持っています。挿入、削除、または更新が行われるたびにキャッシュをクリーンアップします。

これで、潜在的なボトルネックがここに表示されると確信しています。テストでは、ファイルシステムに対して2つ(または新しいIDを追加する必要がある場合は3つ)のリクエストがキャッシュから保存またはフェッチされます。これは、一緒にキャッシュする必要性を打ち負かす可能性さえあります。それで、ファイルシステムやデータベースに保存せずに、phpでクエリの一意のID、つまりはるかに短い表現を生成する方法はありますか?

4

2 に答える 2

1

文字列は任意の長さであるため、重複せずに任意の入力文字列を表すことができる固定サイズの識別子を作成することは明らかに不可能です。ただし、キャッシングの目的では、通常、単純な「十分に優れた」ソリューションで、衝突を許容可能なレベルまで減らすことができます。

たとえば、MD5を使用するだけで、2つの128のケースのうち1つでのみ衝突が発生します。それでも衝突が心配な場合(そしておそらく安全のために)、クエリ結果をキャッシュの「値」に保存し、値が戻ってきたらそれが実際にクエリであることを確認できます。あなたが探していた。

簡単な例として(私のPHPはちょっと錆びていますが、うまくいけばあなたはアイデアを得るでしょう):

$query = "SELECT * FROM ...";

$key = "hash-" + hash("md5", $query);
$result = $cache->load($key);
if ($result == null || $result[0] != $query) {
    // object wasn't in cache, do the real fetch and store it
    $result = $db->execute($query); // etc

    $result = array($query, $result);
    $cache->save($result, $key);
}

// the result is now in $result[1] (the original query is in $result[0])
于 2010-06-21T01:28:23.090 に答える
0

MD5 !!

Md5は、正常に機能しているように見える長さ32の文字列を生成し、キャッシュファイルが作成され(ファイル名は約47)、オペレーティングシステムがそれらを拒否していないように見えます。

//returns id for a given query
function getCacheId($query) {
    return md5($query);
}

以上です!しかし、衝突の問題があり、md5ハッシュ(おそらくテーブルの名前を使用)をソルトすると、より堅牢になるはずです。

//returns id for a given query
function getCacheId($query, $table) {
    return md5($table . $query);
}

結果のキャッシュを実装する方法の完全なコードが必要な場合は、コメントを残してください。喜んで投稿します。

于 2010-06-21T02:52:40.613 に答える