我们目前正在使用CodeIgniter的文件缓存来优化一个繁重的DB查询,该查询在我们的多用户环境中经常被调用,但不会经常更改。缓存设置为每60秒过期一次,因此这意味着查询将每小时调用60次。在DB监视器中,我们看到查询每小时调用340±150次,几乎是预期的六倍。
该代码没有什么特别之处,集所有功能于一身:
// Cache identifier
$cache = 'cache-identifier';
// Try to pull from the cache first
if ($working = $this->cache->file->get($cache))
return $working;
// Cache didn't work out, query directly
$sql = '<<heavy-DB-query>>';
$working = $this->db->query($sql)->result_array();
// Save the cache (note essentially redundant check: $working is 99.95% non-null)
if ($working)
$this->cache->file->save($cache, $working, 60);
return $working;
与非缓存相比,我们确实看到了显著的减少,但希望进行更多优化。你知道为什么它会经常丢失吗?
在缓存之前,我们每小时调用大约3000次DB查询(每分钟50次)。因此,每小时340个电话(每分钟5个电话)是一个显著的改进。我们尝试在出现未命中时输出到日志文件,但这样做似乎改变了动态和统计数据。
单独测试,单用户,从浏览器到服务器再到服务器,未命中大约需要1.0秒,命中大约需要0.6秒。查询本身大约为0.1秒,但在开销方面,服务器到数据库的时间大约为0.5秒。
我认为可能发生的情况是,其他活动的副作用正在导致用户同步,因此我们将查询集中起来,而不是随机的。第一个未命中,进行查询,与第二个、第三个相同,依此类推,直到第一个返回结果。然后那一分钟的剩余部分会被击中。考虑到所涉及的时间,每分钟看5次电话或多或少符合这一假设。但是如何测试呢?
原来服务器访问日志中有答案。它们确实显示了具有相同时间戳的多个查询组。事实证明,用户通常在同一浏览器中打开多个窗口,在这种情况下,查询确实倾向于同步。我在计时器中添加了一个随机元素,以中断此同步。到目前为止,情况似乎有所好转。现在我知道发生了什么,我很乐意每分钟打2个电话!