【问题标题】:Symfony2 and doctrine2 performance of simple DQL querySymfony2和doctrine2的简单DQL查询性能
【发布时间】:2012-09-18 11:33:50
【问题描述】:

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

当我从 symfony 请求一个简单的页面(没有 DB 请求)时,它会在大约 200 毫秒内响应。一旦我通过 Doctrine 从数据库请求任何东西,它就会跳到 ~1300 毫秒。

我很感激有时间补充记录,但这是我为阵列补充水分。

这是控制器代码。模板只输出数组计数。

$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

总计 - 1.0283808708191

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

【问题讨论】:

  • 你是在开发环境中测试这个吗?您应该只在 prod 环境中运行基准测试,开发环境根本没有优化,您不能相信基准测试时间。还要在 prod 环境中运行教义:ensure-production-settings 命令以确保一切都配置好。
  • 切换到 prod 将响应时间降低到一致的 ~ 1000 毫秒,但这仍然非常慢。我开始认为这比 symfony 更像是一个教义问题......
  • 你要检索多少条记录?
  • 这张表有索引吗?如果不订购,是否需要相同的时间?
  • 查看更新 - 它似乎是第一个需要所有时间的查询,即使它只提取一条记录

标签: performance symfony doctrine-orm


【解决方案1】:

所以正如你们建议的那样,它原来是我的环境。也就是说,我在 symfony 中使用 'localhost' 作为 database_host。将其更改为“127.0.0.1”会有所不同。我现在可以快速运行查询。

感谢你们的 cmets 人。

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

【讨论】:

  • 对我来说是 1300 毫秒到 300 毫秒...谢谢!
【解决方案2】:

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

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

【讨论】:

  • 原来是环保的。
猜你喜欢
  • 2015-01-07
  • 2015-08-26
  • 2011-11-16
  • 1970-01-01
  • 1970-01-01
  • 2015-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多