4

以前は、クエリに非常に多くの複数の結合がありました。

(少なくとも) 組み込みの MySql キャッシュ機能を使用できるようにするために、次の関数を作成しました。元のクエリを base64 にエンコードし、クエリが存在し、有効期限が切れていないかどうかを確認します。

これにより、パフォーマンスが劇的に向上し、ソース コードでキャッシュ時間のクエリごとに制御できるという利点があります。

ただし、忙しい時間帯には、削除が原因でテーブルが使用できなくなったり、単に選択に時間がかかりすぎたりします。これをより速く実行し、前述の問題を回避するために何をすべきかについて何か提案はありますか?

テーブル:

CREATE TABLE `cachesql` (
`id` int(9) NOT NULL AUTO_INCREMENT,
`expire` int(15) NOT NULL,
`sql` text NOT NULL,
`data` mediumtext NOT NULL,
PRIMARY KEY (`id`,`sql`(360)),
KEY `sdata` (`sql`(767)) USING HASH
) ENGINE=InnoDB

関数:

    function fetchRows_cache($sql,$cachetime,$dba){
    // internal function (called by fetchRows)
    global $Site;
    $expire = 0;
    $this->connect($dba);

    // check if query is cached
    $this->q = mysql_query("SELECT `expire`,`data` from cachesql where `sql`='".base64_encode($sql)."' limit 1;", $this->con) OR $this->error(1, "query$".$sql."$".mysql_error());
    $this->r = mysql_fetch_assoc($this->q);
    $expire = $this->r['expire'];
    $data = $this->r['data'];

    if (($expire < time())||($cachetime =="0")) { // record expied or not there -> execute query and store
        $this->query("DELETE FROM `cachesql` WHERE `sql`='".base64_encode($sql)."'",$dba); // delete old cached entries

        $this->q = mysql_query($sql, $this->con) OR $this->error(1, "query$".$sql."$".mysql_error());
        $this->r=array();
        $this->rc=0;
        while($row = mysql_fetch_assoc($this->q)){
            $arr_row=array();
            $c=0;
            while ($c < mysql_num_fields($this->q)) {        
                $col = mysql_fetch_field($this->q, $c);    
                $arr_row[$col -> name] = $row[$col -> name];            
                $c++;
            }    
            $this->r[$this->rc] = $arr_row;
            $this->rc++;
        }
        $out = $this->r;

        // write results into cache table
        if ($cachetime != "0") {
            // not store cache values for now (too many locks)
            $this->query("INSERT INTO `cachesql` (`sql`,`data`,`expire`) VALUES ('".base64_encode($sql)."','".mysql_real_escape_string(serialize($out))."','".(time()+$cachetime)."')",$dba);       
        }
        return $out;

    }
    else { // use Cached data
        return unserialize($data); 
    }
}
4

3 に答える 3

0

@HeatfanJohn のおかげで、彼は本当にシンプルで効率的なことを指摘してくれました。

元のクエリは何にも使用されないため (キャッシュ エントリの照合を除く)、問題のクエリを一意に識別するチェックサムを格納するだけで十分です。

新しい構造は、元のクエリの MD5 ハッシュ (16 バイト)、 expireUnixTime 、およびシリアル化された行セットを格納するだけです。

新しい構造:

CREATE TABLE `cachesql` (
`sql` varchar(32) NOT NULL,
`expire` int(11) NOT NULL,
`data` text NOT NULL,
PRIMARY KEY (`sql`),
UNIQUE KEY `sql` (`sql`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='cache for db->fetchRows'

列のプライマリ インデックスはsql非常に短いため、非常に高速に反応し、検索用にインデックスを作成することができます。

データセットに BLOB または TEXT フィールドを使用しても、異なる速度の結果は得られませんでした。

于 2012-09-03T12:58:18.427 に答える
0

主な速度低下のポイントは、キャッシュテーブルに InnoDB を使用していることだと思います。

読み取り負荷の高いキャッシュテーブルを除くすべてに InnoDB を使用する必要があることがわかりました;)

MyISAM は、読み取りが集中する (選択) テーブルに特に適しています。

于 2012-09-03T06:02:11.727 に答える
0

インメモリテーブルを試して高速化してみましょう。

于 2012-09-04T14:25:32.557 に答える