如何从laravel中的雄辩查询中一次获得一行?

时间:2014-04-03 09:23:07

标签: php sql laravel-4 eloquent

假设我有一个简单的查询来从表中获取所有行:

App::make('My_Model')->get();

但是,我有大量的行 - 比如10万,这么多,以至于PHP耗尽内存试图全部读取它们。

出于某种原因,我想浏览每一行,并根据它们进行一些操作。

有没有办法告诉laravel一次给我一行,就像旧mysql_fetch_row的工作方式一样?

注意:我目前正在通过使用limit()命令一次获得5000行来解决这个问题,除了重复查询20次之外,它可以正常工作。

我想知道laravel或eloquent中是否有任何内置方法给我下一行而不是所有行?

4 个答案:

答案 0 :(得分:5)

如果你想要处理它们,一次说一千个,chunk()中的Eloquent方法应该适合你:

My_Model::chunk(1000, function($my_models)
{
    foreach ($my_models as $my_model)
    {
        // do something
    }
});

Eloquent docs

中的更多内容

取决于您对数据做了什么......

答案 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条记录,否则几乎没有理由需要这样做。

  • 如果你想改变一些但不是所有的记录,应该可以建立一个DB :: update()查询来做到这一点,所以你不需要将记录加载到PHP'所有的记忆
  • 如果您只想显示某些记录,则应该可以修改您的$ model查询,这样您只需将记录加载到您实际需要的PHP内存中。
  • 如果您需要实际显示整个记录集,那么您实际上需要逐个遍历它们,但这听起来并不像您尝试做的那样。

向我们提供更多信息,您实际想要完成的是什么?