如何将缓存注入Zend_Db

时间:2011-11-17 23:39:05

标签: php zend-framework caching

我正在寻找减少MySQL服务器上执行的查询数量的方法。

应用程序和数据库服务器位于不同的计算机上,因此似乎在应用程序服务器上缓存以前的查询结果并不是一个糟糕的选择。显然还有其他策略,比如减少查询数量和优化查询语句,但是我认为我不应该将查询缓存作为一种选择。

我最初认为我可以在Zend_Db对象中轻松打开某种形式的查询缓存,但是我最接近看到的是横切的Zend_Db_Profiler

我正在考虑的一种方法是为我的Zend_Db_Adapter对象创建代理。有什么影响:

/**
 * Initialize the database.
 *
 * @return void
 */
protected function _initDb() {
    // Instantiate a connection to the database
    $config = Zend_Registry::get('config');
    $db = new MyProject_Db_Proxy (
                Zend_Db::factory($config->resources->db->adapter, 
                                 $config->resources->db->params)
              );

    // Store the database object in the registry
    Zend_Registry::set('db', $db);

    Zend_Db_Table::setDefaultAdapter('db');
}

我查看了各种Zend_Db接口和类,看起来我可以通过代理将缓存注入Zend_Db_Adapter_Abstract::query()方法。有什么影响:

public MyProject_Db_Proxy() {

  private $_adapter = null;
  ...
  public function query($sql, $bind = array()) {
    // Generate the cache key by joining and hashing $sql and $bind
    // Check to see if key is in cache, return if found
    // Execute query
    $stmt = this->_adapter->query($sql, $bind);
    // Cache result
  }
  ...
}

我的问题是:是否有更好/更简单的方法将缓存注入Zend_Db?

1 个答案:

答案 0 :(得分:1)

我会避免尝试直接将缓存注入Zend_Db。

如果您有一个要缓存24小时的查询,而您只想缓存60秒,该怎么办?你如何/在哪里控制它?你还需要逻辑来确保它只缓存SELECT查询,否则你就是在浪费缓存空间。

我会使用Zend_Cache使用您选择的适配器(libmemcached / apc / xcache以获得最佳性能)并在您的应用程序或数据访问类中处理缓存。

您可以使用查询本身的哈希作为缓存键,或者根据查询数据,为更容易识别的特定查询创建哈希函数。例如,如果您的查询只是从数据库中提取用户帐户详细信息,则缓存密钥可能类似于userInfoQuery:1234,其中1234是用户ID。

The query cache does not return stale data. When tables are modified, any relevant entries in the query cache are flushed.

因此,如果您的表因插入/更新/删除而更改,则会清除查询缓存。如果表经常更改,那么查询缓存不是很有用,因为它是短暂的。

Zend_Db在制作中应该做的另一件常见事情是缓存表元数据。您可能已经注意到,Zend在insert(),find()或info()查询之前发出DESCRIBE查询。使用表元缓存可以消除这些查询。有关如何执行此操作的说明,请参阅caching table metadata