Symfony2和doctrine2表现简单的DQL查询

时间:2012-09-18 11:33:50

标签: performance symfony doctrine-orm

我正在为性能非常重要的网站开发前端。快速开发也很关键,因此我决定使用symfony2并使用Doctrine2 ORM。

当我从symfony请求一个简单的页面(没有DB请求)时,它会在~200ms内响应。一旦我从DB通过Doctrine请求任何内容,它就会跳到大约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,控制器需要大约1000毫秒,而且学说需要大约1毫秒。但是如果我注释掉getResults()行,控制器就会跳到~45ms。

这是正常的吗?我该怎么办?

更新 我运行了以下测试,它显示第一个查询是所有时间丢失的地方:

$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. 1.0216779708862
  2. 0.00091791152954102
  3. 0.00082588195800781
  4. 0.00081419944763184
  5. 0.00081706047058105
  6. 0.00081610679626465
  7. 0.00081491470336914
  8. 0.00081706047058105
  9. 0.00043296813964844
  10. 0.0004270076751709
  11. 总计 - 1.0283808708191

    可能是数据库连接或实体管理器没有被池化吗?

2 个答案:

答案 0 :(得分:1)

正如你们所说,结果证明是我的环境。也就是说,我在symfony中使用'localhost'作为database_host。将它改为'127.0.0.1'就完全不同了。我现在正在快速运行查询。

感谢您的评论。

http://www.bluetopazgames.com/uncategorized/php-mysql_connect-is-slow-1-second-for-localhost-windows-7/

答案 1 :(得分:0)

你猜对了,实体经理在这里采取行动。当您发出$query->getResult()默认水化模式为Query::HYDRATE_OBJECT时。对于此模式,Doctrine2将每个行数据映射到实体对象(对于复杂的实体关系可能非常昂贵)并将它们加载到实体管理器。但是,如果再次发出相同的查询,它将使行标识符与实体管理器中加载的实体对象的标识符相匹配。如果匹配的Doctrine2不会进行映射,则会进行映射并加载(如果不匹配)。

如果多次发出相同的查询,则非常有用。例如,各种服务可以加载用户数据并在页面的各个部分中显示用户信息。如果您确定实体对象将在一个请求周期中加载和使用一次,那么您可以使用$query->getArrayResult()来避免不必要的结果集映射。也就是说,如果使用得当,ORM可以高效:)。有关详细信息,请参阅doc