缓存常规SQL查询非常简单。
public function query($sql) {
if( $result = cache::get(sha1($sql)) ) {
return $result;
}
$result = $this->connection->query($sql);
cache::set(sha1($sql), $result);
return $result;
}
但是如何使用预处理语句缓存查询,因为在语句准备好后数据被绑定之前,您不知道查询将是什么?
$sth = $dbh->prepare('SELECT * FROM table WHERE id = ?');
...later...
$sth->bindParam(1, $id);
$sth->execute();
我觉得这是一个由两部分组成的答案:首先,语句缓存在每页内存中(就像$ this-> statements []的数组一样),因为数据库资源id不会持续很长,不能存储在文件或任何东西。
其次,在执行语句之前()我们在memcached / filecache中查看结果,方法是散列用于创建语句的sql(使用PDOStatement::queryString
轻松)以及给定的params的哈希值。麻烦的是在语句对象中找到params。
当然,这只是一个想法,可能有更好的解决方案。
答案 0 :(得分:1)
好吧,你必须将每个参数的值添加到缓存键中。像这样:
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));
我会留给你根据你的需要调整它。你必须获取行并将它们存储在一个数组中。
这是你必须使用的那种包装器:
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);
}
}
您必须匹配您计划使用的每个PDOStatement方法。 PDO :: FETCH_INTO也很难实现。我的建议:专注于你自己的用法。也许您甚至不必在dbh级别实现缓存,而只能在其重要的位置添加缓存功能。
无论如何,请记住,您编写的代码越多,您需要维护的代码就越多,您在应用程序中引入错误的可能性就越大。因此,请谨慎对待缓存层的成本/收益分析,该缓存层会为了自己的利益而过于聪明:)