ORM查询结果:包含在Iterator接口中的Arrays与Result句柄

时间:2009-02-10 08:55:08

标签: php mysql orm activerecord arrayiterator

好的,这是专业人士的一个:

几年来,我一直致力于自己的PHP ORM / ActiveRecord实现,我命名为Pork.dbObject.

基于“让你自己的网站在5分钟内制作自己的网站”电影,我们几年前都看到了它。你可以这样做:

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

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

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

这将从数据库中获取一行或多行,将它们包装在dbObject中并将它们返回到一个数组中,或者返回false,表示没有结果。

所有这些都在几十个站点和后端中完美运行,但现在我的同事正在使用它来创建一个巨大的logparser,这里开始了内存使用问题..

他运行的查询可以返回超过20,000行,甚至更多,这对于一次性包装到对象包装器并且作为单个数组返回来说并不是一件好事。

显而易见的解决方案是返回一个实现Iterator接口而不是数组的对象。它不应该立即从结果集中获取所有记录,而只是保存生成的数据库查询的结果资源,并在遍历对象时在内部使用mysql_fetch_ *,就像它是一个数组一样。

现在我们来看看我真正的问题: 我可以毫无问题地这样做吗?数据库是否能够处理多个打开的结果集,并将它们混合并将它们保留在内存中一段时间​​?

例如,获取20个对象,循环它们,让这20个中的每一个获取5个其他对象,然后再获取3个其他对象。这将创建一个循环,其中许多不同的结果句柄将保留在内存中。

我知道我无法序列化其中一个对象,但我能否在PHP5中实现这一点而没有任何问题,或者数据库接口会给我带来问题吗?

1 个答案:

答案 0 :(得分:2)

这取决于您使用的数据库和数据库配置。

对于MySQL,您需要确保使用缓冲查询。在PDO中,您可以这样设置:

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

这意味着所有数据都将被发送到客户端(与在PHP中获取所有数据不同)。

另一个(可能更糟糕的)替代方法是每当检测到结果集仍处于打开状态时运行的查询时打开新的数据库连接。

普通mysql_query()使用缓冲查询,因此可以使用多个结果集。