我正在使用CakePHP和$ modelName-> find(...) 调用选择相当多的行(可能是数百个)
通常情况下,在PHP / MySQL当然这不是问题,因为你在while循环中获取它们。 但是,CakePHP将所有行加载到一个耗尽内存的数组中 限制。
有没有办法使用$ modelName-> find(...)构造但返回一个 迭代器按需获取每一行?
谢谢, 大卫
答案 0 :(得分:4)
如果您的问题是由模型的关系引起的,则可以通过这种方式减少递归:
$ modelname-> recursive = -1;
然后你只会得到当前模型的数据,没有任何关系。
迭代所有记录,您将能够逐个获得他们的关系,再次使用递归>查询; 0
答案 1 :(得分:3)
以下是可用于一次处理几行的表的代码
$limit = 10;
$loop_no = 0;
do {
$handles = $this->SocialChannelHandle->find('all', array(
'fields' => array('brand_id', 'handle'),
'conditions' => array('social_channel_id' => $facebook['SocialChannel']['id']),
'limit' => $limit,
'offset' => $limit * $loop_no,
'order' => 'id asc',
'recursive' => -1)
);
$loop_no++;
} while (count($handles) == $limit);
答案 2 :(得分:2)
不,开箱即用的Cake PHP(以及一般的ActiveRecord)不支持迭代结果集。如果您有一个用例,其中您实际需要 all 表的记录,那么您最好使用原始SQL。 (或重新考虑你的用例)。
您也可以(并且可能已经考虑过)使用某种偏移量,然后调用 - >多次查找。如果采用这种方法,请不要忘记按某个字段对结果集进行排序,以确保确定性结果。当您关闭ORDER BY时,数据库似乎只返回已排序的行。我没有亲自试过这个,从多个查询的角度来看似乎效率低下,但这是值得尝试的。
答案 3 :(得分:0)
如果您正在使用存储过程来生成查询,那么模仿分页行为以一次获取查询段可能是个好主意。在这种情况下,您将向起始行索引和“page”-size的存储过程发送两个额外参数,并返回调整select语句以仅检索row_index + 1和row_index + page_size之间的那些记录。 / p>
这可以全部放入一个额外的循环层,所以你得到一个新的段,然后在其中通过该段中的每一行。
答案 4 :(得分:0)
由于您的模型关系,您可能也会获得如此多的数据。对于someModel-> find()调用,有多少其他模型与someModel相关?
我在典型的共享托管服务器上的阵列中至少使用了1000行而没有内存问题。
更新:如果您不想返回相关模型,则可以简单地使用Containable行为。因此,如果您尝试查找所有帖子但不想要评论,则可以使用$ this-> Post-> contains()语法仅返回Post记录。 Containable是一种必须使用$ actAs参数添加到模型中的行为,$ actAs = array('Containable');
答案 5 :(得分:0)
我知道您正在寻找从查找条件返回的迭代器,但是如何使用带有可变偏移量的LIMIT子句(例如,您希望一次返回的行数)?这可能会带来一些并发问题,但是如果还包含ORDER BY id子句,则应该在返回的行中看到一致的行为。然后,在循环中,只需重复发出find(...)查询。
这显然不像迭代器那样是一个优雅的解决方案,但我想,重复发出返回更多行的请求的开销将通过一次检索多行来节省成本(在蛋糕)。
最后,如果你真的在寻找性能,那么我认为CakePHP可能不是你的茶包。新版本的速度正在提高,但我相信它在性能方面仍然落后于其他框架。
答案 6 :(得分:0)
我想这是不可能的,因为CakePHP正在动态构建一个表示数据库实体关系的多维数组。这应该在获取所有查询行之后完成,以便CakePHP知道所有可能的相关实体。
示例:
需要获取3行才能构建相应的多维数组:
Article 1 | -- Comment 1 | -- Comment 2 | -- Comment 3
查询结果(1..n):
Article | Comment ----------------- 1 | 1 ----------------- 1 | 2 ----------------- 1 | 3
答案 7 :(得分:0)
您可以为查找请求添加限制。我现在没时间写完整的答案。我稍后会更新。
不,据我所知,当你在mysql或普通驱动程序中执行请求时。无论如何它都会返回你选择的所有元素。因此,如果你有内存限制的问题,它可能在其他地方。您可以为特定行数添加限制。如果您的表具有多个依赖项,但您不需要加载每个外键,则可以使用“contains”属性来仅加载所需的内容。
你能告诉我们你的桌子吗?以及你想要选择的内容。
答案 8 :(得分:0)
您可以使用递归参数(API for Model#find)限制查找方法调用,也可以动态取消绑定模型关联并减少检索的数据量(Creating and Destroying Associations on the Fly)
答案 9 :(得分:0)
已经有一段时间了,但是由于搜索中出现了这个问题,我想提到实际上有一种内置方法可以做到这一点。 类似的东西:
$page = 1;
$limit = 100;
while ($posts = $this->Post->find('all', array(
'conditions' => ...,
'page' => $page,
'limit' => $limit,
...
))) {
foreach ($posts as $post) {
...deal with one row...
}
$page++;
}
将对数据集进行分页,但由于在每个while循环中重新执行查询,因此会有一些性能损失。
(未经测试)
答案 10 :(得分:-1)
Ruby On rails可以更好地处理这个问题。除非您使用以下内容,否则默认行为不包括任何其他表:include => :table_name然后它将动态生成连接..
没有理由不这样做,只是没有。