假设我有一个简单的查询来从表中获取所有行:
App::make('My_Model')->get();
但是,我有大量的行 - 比如10万,这么多,以至于PHP耗尽内存试图全部读取它们。
出于某种原因,我想浏览每一行,并根据它们进行一些操作。
有没有办法告诉laravel一次给我一行,就像旧mysql_fetch_row的工作方式一样?
注意:我目前正在通过使用limit()命令一次获得5000行来解决这个问题,除了重复查询20次之外,它可以正常工作。
我想知道laravel或eloquent中是否有任何内置方法给我下一行而不是所有行?
答案 0 :(得分:5)
如果你想要处理它们,一次说一千个,chunk()
中的Eloquent
方法应该适合你:
My_Model::chunk(1000, function($my_models)
{
foreach ($my_models as $my_model)
{
// do something
}
});
中的更多内容
取决于您对数据做了什么......
答案 1 :(得分:5)
对于任何使用Laravel 5.2+登陆的人(就像我一样)现在有了一个游标'返回Generator
的方法https://laravel.com/api/5.2/Illuminate/Database/Query/Builder.html#method_cursor
因此,而不是 - > get()使用 - > cursor()
答案 2 :(得分:1)
问题是,应用程序中的下一行是什么?除非您正在构建具有游标的命令行应用程序,否则您的应用程序仅适用于请求。 Laravel可以为您提供获取光标子集的方法,因此如果您需要5000行,则可以同时获得这5000行。
所以你可以使用paginate:
$someUsers = User::where('votes', '>', 100)->paginate(5000);
采取并跳过:
$page = 5;
$pageSize = 5000;
$users = User::skip($page * $pageSize)->take($pageSize)->get();
Chunk,内部使用paginagion,但它有点限制,因为它会强制你处理你的整个游标:
User::chunk(5000, function($users)
{
/// every time this clojure is ran you get a new subset of 5000 rows.
foreach ($users as $user)
{
// do whatever you need with them
}
});
旁注:您可以通过关闭查询日志来节省内存:
DB::disableQueryLog();
答案 3 :(得分:0)
您尝试进行哪种操作?您描述它的方式是将所有100,000条记录加载到活动内存中,但除非您确实要显示所有100,000条记录,否则几乎没有理由需要这样做。
向我们提供更多信息,您实际想要完成的是什么?