0

パフォーマンスが非常に重要なサイトのフロント エンドを開発しています。迅速な開発も重要だったので、symfony2 を採用し、Doctrine2 ORM を使用することにしました。

symfony から (DB リクエストなしで) シンプルなページをリクエストすると、~200ms で応答します。Doctrine を介して DB に何かを要求するとすぐに、最大 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 プロファイラー ツールバーのティムラインを見ると、コントローラーは約 1000 ミリ秒、doctrine は約 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

おそらく、データベース接続またはエンティティマネージャーがプールされていない可能性がありますか?

4

2 に答える 2

1

おっしゃる通り、私の環境でした。つまり、symfony で database_host として「localhost」を使用していたことです。「127.0.0.1」に変更すると、すべての違いが生じました。現在、クエリを適切に高速に実行しています。

コメントありがとうございます。

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

于 2012-09-19T09:39:11.813 に答える
0

ご想像のとおり、エンティティ マネージャーがここで機能します。発行時の$query->getResult()デフォルトの水分補給モードは ですQuery::HYDRATE_OBJECT。このモードでは、Doctrine2 は各行データをエンティティ オブジェクト (複雑なエンティティ関係では非常にコストがかかる可能性があります) にマップし、それらをエンティティ マネージャにロードします。ただし、同じクエリを再度発行すると、行識別子がエンティティ マネージャーに読み込まれたエンティティ オブジェクトの識別子と一致します。一致した場合、Doctrine2 はマッピングを行わず、一致しない場合はマッピングとロードを行います。

同じクエリを複数回発行する場合に便利です。たとえば、さまざまなサービスがユーザー データを読み込んで、ページのさまざまな部分にユーザー情報を表示できます。エンティティ オブジェクトが 1 回の要求サイクルで 1 回だけ読み込まれて使用されることが確実な場合は、 を使用$query->getArrayResult()して不要な結果セット マッピングを回避できます。そうは言っても、適切に使用すればORMは効率的です:)。詳細については、ドキュメントを参照してください。

于 2012-09-18T18:46:00.500 に答える