【问题标题】:How to inject caching into Zend_Db如何将缓存注入 Zend_Db
【发布时间】:2011-11-17 23:39:05
【问题描述】:

我正在寻找减少在我的 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?

【问题讨论】:

  • 启用您的数据库查询缓存。
  • 请注意,我使用的是 Zend Framework 1.11.11 和 PDO MySQL 适配器。
  • @hakre 您是否建议数据库查询缓存将摆脱网络往返?你能指点我这方面的资源吗?
  • 不,它不会用于网络往返。如果要防止网络往返,需要客户端查询缓存,见forge.mysql.com/wiki/MySQLnd_Query_Cache_Plugin_for_PHP
  • @hakre 我会记住这个插件。它相当新,可能需要升级数据库,但它可能是一种选择。

标签: php zend-framework caching


【解决方案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

【讨论】:

  • 我的方法基本上是相同的,除了我将它全部推送到一个存储库/服务类中,该类提供一个正确配置的(生命周期等)Zend_Cache 实例。在执行昂贵的数据库操作之前,repo/service 中的所有这些数据访问方法都会执行缓存检查。而且,不要忘记,正如 Drew 所指出的,当您更新数据库中任何会影响选择查询结果的数据时,您可能希望清除所有受影响的缓存条目。
  • 感谢您的回答@drew010。元数据缓存似乎是一个非常轻松的选择,可以立即实施。
  • 我是 DRY 的忠实粉丝,所以我希望尽量减少 if key in cache return value else execute query, cache result and return 逻辑的数量。也许在我的映射器中进行一些重构,这可能会成为更好的选择。
猜你喜欢
  • 2012-02-27
  • 2010-11-01
  • 2012-07-03
  • 1970-01-01
  • 2018-04-23
  • 2011-04-23
  • 1970-01-01
  • 2012-04-02
  • 2018-06-18
相关资源
最近更新 更多