我最近阅读了许多关于PHP应用程序可伸缩性的文章。我读过的几乎所有文章都提到了缓存,所以我提出了在类属性中缓存DB数据的想法,以防止过多的数据库查询。我想分享这个想法,所以我在博客上写了这篇文章,只是让老师告诉我这是毫无意义和愚蠢的。除了使用毫无意义和愚蠢的话,他无法解释为什么它是坏的。有人可以在这里解释为什么这种缓存方法,以帮助扩展PHP应用程序是不是很糟糕?
方法:
理论值:
不是从DB中获取每个方法(如果需要)中的数据,而是在查询后执行查询,我认为有一个类属性(变量)存储获取的DB数据是个好主意,以防止需要重复的查询或将返回相同数据的查询。
如果你没有得到这个,这是我博客上的一个例子:
我将把Facebook带入这个例子,只是为了简化解释。假设我们正在重新编码社交网络的用户类。
class FBuser
{
}
此类包含的明显方法:
getStatusUpdates()
getAccountInfo()
getFriendIDs()
最初,这些方法都必须执行数据库查询才能获得所需的数据。但是使用缓存方法,我会定义一个类属性来存储缓存的数据,并且可以在一个方法中进行所有的数据库查询:
class FBuser
{
private $userCache = array();
private function getData( $dataToGet = '' )
{
//all of my db querying would happen here
}
}
但是在同样的方法中,如果我被允许这样做,我也会寻找缓存:
private function getData( $dataToGet = '' , $useCache = true )
{
//am I allowed to use cache?
if ( $useCache === true )
{
//does the appropriate data exist in cache?
if ( isset($this->userCache[ $dataToGet ]) )
{
return $this->userCache[ $dataToGet ];//return the cached data, and forget about the DB queries
}
}
//if we get here, caching was disabled or the required data has not yet been cached :(
//all of my db querying would happen here
//store the data that's just been fetched by the queries in the cache property
}
这样,每当我想从数据库中获取数据时,我都可以调用getData( 'the data I want' , true );
,这样我就可以在何时何地使用缓存数据。
因此,如果我需要多次调用getAccountInfo()
,getStatusUpdates()
或getFriendIDs()
,此方法将阻止执行多个数据库查询=有利于扩展(我认为)。< / p>
答案 0 :(得分:3)
为什么这是一个坏主意?
严格地说 本身 并不是一个坏主意,因为它会按照你的预期做到,并且会有一些性能提升如果您的脚本中有重复的查询。
但实际上,除非你的脚本做得非常好,异常,否则典型PHP脚本的每个请求的数据库调用次数不会超过15或20,并且那些也许只有2 o 3是重复的顶部。如果数据库调用已经相对较快,那么haxing 2或3个数据库调用的性能差异可忽略不计。更不用说数据库本身可能已经有缓存系统了!
实现持久缓存(存在于请求之间的缓存)是潜在性能累积奖金的位置,具体取决于您的应用程序/脚本。
我不是说“不要这样做”,我只是说,除非你打算在同一个请求/脚本中运行相同的查询数百次,这通常是不太可能,没有持久的解决方案,你不会看到太多的东西;但它绝对不会受到伤害。
答案 1 :(得分:1)
你的老师很傻:p
我要说的是,这种类型的缓存,取决于上下文,实际上可能非常有用。我在我开发的Web框架中做了一些,这个重构是通过使用XDebug仔细分析cachegrinds来实现的。
以这种方式思考。您的数据库访问是您的PHP脚本将执行的一些最昂贵的(在性能方面)工作。很容易找到与DB相关的调用占页面总执行时间的50%(或更多)的页面。为什么不缓存结果,以便重新使用数据自动受益?
没有理由不在PHP资源分配方面,因为除非它们被修改,否则PHP将共享对zval的引用,因此你的脚本将不需要更多的内存堆,
对于那些怀疑这一点的人,我要求他们在一个只调用两个数据库调用的页面上运行XDebug,然后向世界宣告他们看不到重要的结果。当实现这个的代码如此简单时,为什么不进行改进呢?
现在,有些人可能会指出更持久的缓存形式,并说你应该使用它们的INSTEAD。我不同意这种反应所暗示的普遍性。也许该数据集太大而无法完全缓存在服务器上。例如,当每天只有1%的用户登录时,我不会将每个人的数据缓存在内存中。它不值得服务器上的内存。也许数据经常更新,在这种情况下,同步成为一个问题/负担,可能超过缓存的好处。我要说的是,在某些情况下,更持久的缓存形式并不合适。
绿色,每个周期都很重要:)