2

さて、これがプロのためのものです:

ここ数年、私はPork.dbObjectという名前の自分のPHP ORM/ActiveRecord実装に取り​​組んできました。

これは、数年前に私たち全員が見た「5分でレールを使って自分のサイトを作る」という映画に大まかに基づいています。次のようなことができます。

$clients = dbObject::Search("Client", array("ID > 500")); 

また

$client = new Client(218); // fetch row with id 218 from client table

また

$projects = $client->Find('Project');

これにより、データベースから1つ以上の行がフェッチされ、それらがdbObjectでラップされて、1つの配列で返されるか、結果がない場合はfalseが返されます。

これらはすべて、数十のサイトとバックエンドで完全に機能していますが、現在、私の同僚はそれを使用して巨大なlogparserを作成しており、ここでメモリ使用量の問題が発生します。

彼が実行するクエリは、20.000行以上、場合によってはそれ以上を返す可能性があります。これは、もちろん、オブジェクトラッパーに一度にラップして、単一の配列として返すのはあまり良いことではありません。

明らかな解決策は、配列の代わりにIteratorインターフェースを実装するオブジェクトを返すことです。結果セットからすべてのレコードを即座にフェッチする必要はありませんが、生成されたデータベースクエリの結果リソースを保持し、オブジェクトを配列であるかのようにトラバースするときにmysql_fetch_*を内部で使用します。

今、私たちは私の本当の質問に行き着きます:私は問題なくこれをすることができますか?データベースは複数の開いている結果セットを処理し、それらを混合してしばらくの間メモリに保持することができますか?

たとえば、20個のオブジェクトをフェッチしてループし、これらの20個のオブジェクトのそれぞれに5個のオブジェクトをフェッチさせ、順番に3個のオブジェクトもフェッチします。これにより、多数の異なる結果ハンドルがメモリに保持されるループが作成されます。

これらのオブジェクトの1つをシリアル化できないことは知っていますが、PHP5で問題なくこれを実装できますか、それともデータベースインターフェイスで問題が発生しますか?

4

1 に答える 1

2

使用しているデータベースとデータベース構成によって異なります。

MySQLの場合、バッファリングされたクエリを使用していることを確認する必要があります。PDOでは、次のように設定します。

$myPdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);

これは、すべてのデータがクライアントに送信されることを意味します(PHPですべてをフェッチするのと同じではありません)。

もう1つの(おそらくもっと悪い)代替手段は、結果セットが開いたまま実行されているクエリを検出するたびに、新しいデータベース接続を開くことです。

通常mysql_query()はバッファリングされたクエリを使用するため、複数の結果セットで機能します。

于 2009-02-10T09:05:17.510 に答える