4

Doctrine MongoDB ODM を使用して、リモートの MongoDB データベースから少数のドキュメントを取得しています。

約 12 個の一致するドキュメントを検索するのに、クエリがわずか 1 ミリ秒しかかからないことを確認しました。(例: Explain 出力からの 'millis':1)。しかし、結果の反復処理には約 250 ミリ秒かかりました。

次のオプションの組み合わせを試したところ、パフォーマンスが向上しませんでした

  • select('名前')
  • 水和物(false)
  • 熱心なカーソル(真)
  • リミット(1)

この遅延を最小限に抑えるにはどうすればよいですか?


更新:サンプル コードによる詳細な説明

$qb = $dm->createQueryBuilder('Books');
$books = $qb->select('name')
            ->field('userId')->equals(123)
            ->field('status')->equals('active')
            ->eagerCursor(true)  // Fetch all data at once
            ->getQuery()
            ->execute();

/**
 * Due to using Eager Cursor, the database connection should be closed and
 * all data should be in memory now.
 */

// POINT A
foreach($books as $book) {
    // I do nothing here. Just looping through the results.
}
// POINT B.

/**
 * From POINT A to POINT B takes roughly 250ms when the query had 12 matching docs.
 * And this doesn't seem to be affected much by the number of records matched.
 * As the data is already in the memory, I expected this to be done in range of 
 * 5~10ms, not 250ms.
 *
 * Am I misunderstanding the meaning of Eager Cursor?
 */
4

2 に答える 2

0

ここには 2 つの間隔があります。1 つはコードの開始点からポイント A までです。2 つ目は A 地点から B 地点までです。.explain() で測定されるのは前者です。あなたが測定しているのは後者です。

特に、BSON ドキュメントがクライアント (PHP プログラム) に転送された後も、デシリアライズして PHP オブジェクトに変換する必要があります。Doctrine を使用している場合は、追加の処理も実行する必要があります。

表示されている時間は、逆シリアル化プロセスの時間です。書類のサイズは?ドキュメントのコンテンツ全体を逆シリアル化する必要があります。これらが大きいか複雑な場合 (深くネストされている、多くの配列など)、これには時間がかかることがあります。

必要なフィールドのみを取得することで、逆シリアル化の時間を短縮できます。クエリに ->select('_id') を追加すると、ループ時間が大幅に短縮されます。

于 2013-01-08T00:59:13.643 に答える
0

OK、Eager Cursor の意味を誤解していたようです。

http://docs.doctrine-project.org/projects/doctrine-mongodb-odm/en/latest/reference/eager-cursors.htmlこのドキュメントは、 execute()が呼び出されると、すべての結果がメモリに取得される ことを示唆しています。しかし、それは正確ではありません。代わりに、EasgerCursor が初めてアクセスされたときにレコードがフェッチされていることがわかりました。

EagerCursor のinitialize()関数では、通常の Mongo Cursor のインスタンスが取得され、他のいくつかの関数を通過した後、最終的にiterator_to_array()関数に渡されます。これは、Mongo Driver がレコードを取得するという実際の作業を行うときであると確信しています。

私の場合、これはforeachループで発生します。したがって、ポイント A とポイント B の間で遅延が観察されました。これを確認するために、MongoClient の実装を試してみたところ、実装間の全体的な時間が非常に近いことがわかりました。

助けてくれてありがとう。

于 2013-01-08T23:27:03.437 に答える