在新服务器上加载 Symfony 1.4 中的列表页需要 ~10 秒


Loading a list page in Symfony 1.4 taking ~10 secs on new server

我从在托管主机上运行 centOS 的旧服务器迁移到在 AWS 中运行 Ubuntu 的新服务器。

移动后,我注意到加载项目列表的页面现在需要 ~10-12 秒才能呈现(有时甚至长达 74 秒(。这在旧服务器上从未被注意到。我使用newrelic查看了这么长时间的时间,发现sfPHPView->render((花费了99%的时间。从nerelic开始,大约有~500次调用数据库来呈现页面。

该页面是一个想法列表,每个想法一行。我使用Doctrine 1.2的$idea->getAccounts((->getSlug((功能。其中 accounts 是另一个与作为外国关系的想法相关联的表。对于每个想法行,都会多次调用此值。部分当前不用于保存每个行元素的代码。

  1. 对行元素使用部分是否有性能优势?(暂时忽略代码可维护性的好处(
  2. 引用通过外部关系连接的数据的最佳实践是什么?我很惊讶每次调用$idea->getAccounts((->getSlug((时都会调用数据库。
  3. 在 ubuntu 中有什么明显的东西会让 sfPHPView->render(( 运行得比 centOS 慢吗?

我会给你我的想法

  • 对行元素使用 partial 时,将其放入缓存中会更容易,因为您可以通过 partial 仿射缓存。

  • 由于在进行查询时未显式定义关系,因此 Doctrine 不会使用关系将所有元素水化。对于这一点,您可以手动定义要补水的关系。然后,您的调用$idea->getAccounts()->getSlug()不会每次都执行新查询。

$q = $this->createQuery();
$q->leftJoin('Idea.Account');
  • 不知道第 3 点。

PS:对于第 2 点,当您想要显示来自关系的信息(在列表视图中(时,在 admin gen 中有很多查询是很常见的。解决方案是定义检索数据的方法:

在你的生成器.yml中:

list:
  table_method: retrieveForBackendList

在 IdeaTable 中:

public function retrieveForBackendList(Doctrine_Query $q)
{
  $rootAlias = $q->getRootAlias();
  $q->leftJoin($rootAlias . '.Account');
  return $q;
}

虽然除了 jOk 的建议之外,我还想添加我还做了什么来提高页面加载速度。

除了显式联接之外,我还做了以下操作:

  1. 切换到返回 DQL 查询对象,然后将其传递给 Doctrine 的paginator
  2. 从使用 include_partial() 更改为 PHP 的include(),减少了include_partial()的对象创建时间
  3. 将数据库中的数据冻结为数组而不是对象
  4. 通过在数据库中执行更多 leftJoin 来删除一些 foreach 循环
  5. 使用结果和查询缓存来减少数据库调用次数
  6. 使用视图缓存减少 PHP 模板生成时间

有趣的是,通过执行 1 到 4,它使 5 和 6 更有效且更容易实现。我认为在开始使用缓存之前,改进您的代码有一些话要说。