dongshan4549 2009-12-06 20:00
浏览 16
已采纳

你如何在准备好的陈述中使用memcached?

Caching regular SQL queries is simple enough.

public function query($sql) {

    if( $result = cache::get(sha1($sql)) ) {
        return $result;
    }

    $result = $this->connection->query($sql);
    cache::set(sha1($sql), $result);
    return $result;
}

But how do you cache queries with prepared statements since you don't know what the query will be until after the statement is already prepared and then the data is bound?

$sth = $dbh->prepare('SELECT * FROM table WHERE id = ?');

...later...

$sth->bindParam(1, $id);
$sth->execute();

I get the feeling that this is a two-part answer: First, the statements are cached in per-page memory (like an array of $this->statements[]) since the database resource ids won't last long and can't be stored in files or anything.

Second, before the statements are executed() we look in memcached/filecache for the results by hashing the sql used to create the statement (easy with PDOStatement::queryString) plus the hashes of the params given. The trouble is finding the params in the statement object.

Of course, this is just one idea and there are probably better solutions.

  • 写回答

1条回答 默认 最新

  • doubiaozhan0745 2009-12-06 20:13
    关注

    Well, you have to add the value of each of your params to your cache key. Something like this:

    public function stmt($sql, $params) {
    
        $cache_key = sha1($sql . serialize($params));
    
        if( $result = cache::get($cache_key) ) {
            return $result;
        }
    
        $sth = $this->connection->prepare($sql);
    
        $i = 0;
        foreach ($params as &$param)
        {
            $sth->bindParam(++$i, $param);
            $sth->execute();
        }
        unset($param)
    
        // fetch all the rows into $result
    
        cache::set($cache_key, $result);
        return $result;
    }
    
    $obj->stmt('SELECT * FROM table WHERE id = ?', array(&$id));
    

    I'll leave it to you to adapt it to your needs. You'll have to fetch the rows and store them in an array.


    Here's the kind of wrapper you'd have to use:

    class stmt
    {
        protected $sth, $sql, $cache, $params = array();
    
        public function __construct($dbh, $sql)
        {
            $this->sth = $dbh->prepare($sql);
            $this->sql = $sql;
        }
    
        public function bindParam($param, &$var)
        {
            $this->params[$param] =& $var;
            return $this->sth->bindParam($param, $var);
    
            // or, if you want to support all the args
            $args = func_get_args();
            $args[1] =& $var;
    
            return call_user_func_array(array($this->sth, 'bindParam'), $args);
        }
    
        public function execute(array $params = null)
        {
            $str = serialize(isset($params) ? $params : $this->params);
            $cache_key = sha1($this->sql . $str);
    
            // insert cache logic here...
    
            if (isset($params))
            {
                $this->stmt->execute($params);
            }
            else
            {
                $this->stmt->execute();
            }
    
            $this->cache = $this->stmt->fetchAll();
    
            // save cache here
        }
    
        public function fetch()
        {
            return array_shift($this->cache);
        }
    }
    

    You'd have to match every PDOStatement method you plan to use. PDO::FETCH_INTO would be kind of a pain to implement, too. My advice: focus on your own usage. Perhaps you don't even have to implement a cache at the dbh level and instead you can add caching capabilities only where it counts.

    At any rate, keep in mind that the more code you write, the more code you'll have to maintain and the more likely it is you will introduce bugs in your application. So be careful with the cost/benefits analysis of a caching layer that would try to be too smart for its own good :)

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥60 pb数据库修改或者求完整pb库存系统,需为pb自带数据库
  • ¥15 spss统计中二分类变量和有序变量的相关性分析可以用kendall相关分析吗?
  • ¥15 拟通过pc下指令到安卓系统,如果追求响应速度,尽可能无延迟,是不是用安卓模拟器会优于实体的安卓手机?如果是,可以快多少毫秒?
  • ¥20 神经网络Sequential name=sequential, built=False
  • ¥16 Qphython 用xlrd读取excel报错
  • ¥15 单片机学习顺序问题!!
  • ¥15 ikuai客户端多拨vpn,重启总是有个别重拨不上
  • ¥20 关于#anlogic#sdram#的问题,如何解决?(关键词-performance)
  • ¥15 相敏解调 matlab
  • ¥15 求lingo代码和思路