2013-01-07 76 views
3

缓存PDO预处理语句我在更新旧(乱)的请求mysql_query)代码(以PDO的过程。在类包装

据我所知,使用预处理语句是良好的安全性和性能,但是在性能方面开始发挥作用时,准备必须完成之后先多执行。这意味着我的代码中的主要重写可能不值得提高性能,但是我想知道我是否可以以另一种方式做到这一点。

我提出的解决办法是包裹PDO类,如下所示:

class PDOCached extends PDO { 

     private $PreparedStatementCache; 

     public function prepare($query) { 

      if (!isset($this->PreparedStatementCache[$query])) {    
       $this->PreparedStatementCache[$query]=parent::prepare($query); 
      } 

      return $this->PreparedStatementCache[$query]; 
     } 
} 

它的工作原理(即我得到同样的结果。),但我并不清楚它是否可以让我有机可乘性能提升。任何反馈/评论赞赏。

注:我知道这并没有考虑到$ driver_options,但这项工作是不是很重要。


UPDATE:

我已经修改了类,使缓存可选:

class PDOCached extends PDO { 

     private $PreparedStatementCache; 

     // WARNING: Does not take into account $driver_options 
     public function prepare($query, $cached=false) { 

      if (!$cached) return parent::prepare($query); 

      if (!isset($this->PreparedStatementCache[$query])) { 
       // WARNING: Assumes try/catch error handling    
       $this->PreparedStatementCache[$query]=parent::prepare($query); 
      } 

      return $this->PreparedStatementCache[$query]; 
     } 
} 
+0

典型的web应用很少运行中处理单一请求类似的查询。你确定你有这种情况吗?你不觉得如何使用JOIN或IN来重写它们吗? –

+0

我有一些地方有一个循环根据上下文调用几个不同的函数之一。在这些功能中,特定记录的数据将被检索并格式化以供演示。重写代码或在循环外部移动准备语句将是一件大事,所以我正在寻找这样的替代方案。 –

回答

1

从技术性能的角度来看,你是正确的。您将从缓存PDOStatement中获益(必须在相同的连接中使用)。但是,在同一个Mysql连接和PHP请求中,多久执行一次查询,继续执行另一个查询,然后再返回到第一个查询?这看起来会让人困惑并且打开错误地改变绑定变量的可能性(如果使用bindParam())。

我想你会从这个发现的性能增益只有微的优化,你会仅仅是增加了复杂性 - 不是一件好事,因为它已经足够复杂,你需要花时间去清理循环查询不具有重叠的嵌套查询需要。

BTW:单独的安全性是绰绰有余的一个很好的理由移动到准备好的发言和投资转换时间更多。

+0

我没有缓存查询字符串,我正在缓存由PDO :: prepare返回的语句对象。查询字符串只是缓存语句对象的数组中的键。 –

+0

@BenHolness明白了。如果你在同一个连接上持有PDOStatement对象,那么它在技术上应该是'更快'的,因为你没有计算出它将如何再次执行。看我的更新 – Ray

+0

酷。所以我现在已经在PDOCached的准备函数中添加了一个'cached'参数,所以我只使用它,当我知道一个语句将在一次页面加载中被多次使用时,那么我应该获得性能优势以及安全优势(尽管原始代码中的所有内容都已经被清除,所以我不知道这会多加多少)。我已经使用新代码更新了原始帖子。 –