我正在为一个性能非常重要的网站开发前端。快速开发也是关键,所以我决定使用symfony2并使用Doctrine2 ORM。
当我从symfony请求一个简单的页面(没有DB请求)时,它会在大约200ms内做出响应。只要我通过条令向DB请求任何东西,它就会跳到大约1300ms。
我很感激有时间来补充记录,但这是我对阵列的补充。
这是控制器代码。模板只输出数组计数。
$repository = $this->getDoctrine()->getManager()->getRepository('AcmeProductBundle:Product');
$qb = $repository->createQueryBuilder('g');
$qb->addOrderBy('g.id', 'DESC');
$ret = null;
$query = $qb->getQuery();
//$query->useResultCache(true, 3600);
$ret = $query->getArrayResult();
return $this->render('AcmeCatalogBundle::test.html.twig', array('id' => count($ret)));
查看symfony profiler工具栏中的Timline,控制器花费约1000ms,条令花费约1ms。但如果我注释掉getResults()行,控制器会跳到~45ms。
这正常吗?我该怎么办?
UPDATE我运行了以下测试,它显示第一个查询是所有时间丢失的地方:
$ret = array();
$start = microtime(true);
for ($i = 1; $i <= 10; $i++) {
$time_start = microtime(true);
$query = $em->createQuery('SELECT p FROM AcmeProductBundle:Product p WHERE p.id = 1');
$products = $query->getResult();
$time_end = microtime(true);
$ret[$i] = $time_end - $time_start;
}
$end = microtime(true);
$ret['Total'] = $end - $start;
return $this->render('AcmeCatalogBundle::test.html.twig', array('ret' => $ret));
结果:
- 1.0216779708862
- 0.00091791152954102
- 0.00082588195800781
- 0.00081419944763184
- 0.00081706047058105
- 0.00081610679626465
- 0.00081491470336914
- 0.00081706047058105
- 0.00043296813964844
- 0.0004270076751709
总计-1.0283808708191
可能是数据库连接或实体管理器没有被池化吗?
所以,正如你们所建议的,这是我的环境。也就是说,我使用"localhost"作为symfony中的database_host。将其更改为"127.0.0.1"使其完全不同。我现在以适当的速度运行查询。
谢谢大家的评论。
http://www.bluetopazgames.com/uncategorized/php-mysql_connect-is-slow-1-second-for-localhost-windows-7/
您猜对了,实体经理在这里开始行动。当您发布$query->getResult()
时,默认水合模式为Query::HYDRATE_OBJECT
。对于这种模式,Doctrine2将把每一行数据映射到实体对象(对于复杂的实体关系来说,这可能非常昂贵),并将它们加载到实体管理器中。但如果您再次发出相同的查询,它将使行标识符与实体管理器中加载的实体对象的标识符相匹配。如果匹配,Doctrine2将不进行映射,如果不匹配,将进行映射和加载。
若多次发出相同的查询,则会很有用。例如,各种服务可以加载用户数据并在页面的各个部分显示用户信息。如果您确信实体对象将在一个请求周期中被加载和使用一次,那么您可以使用$query->getArrayResult()
来避免不必要的结果集映射。也就是说,如果使用得当,ORM可能是高效的:)。有关更多信息,请参阅文档。