laravel 游标和 laravel chunk 方法有什么区别?

2022-08-30 10:56:49

我想知道laravel chunk和laravel cursor方法有什么区别。哪种方法更适合使用?它们两者的用例是什么?我知道你应该使用光标来节省内存,但它在后端是如何工作的?

带有示例的详细说明会很有用,因为我已经在stackoverflow和其他网站上进行了搜索,但我没有找到太多信息。

这是来自laravel文档的代码片段。

分块结果

Flight::chunk(200, function ($flights) {
    foreach ($flights as $flight) {
        //
    }
});

使用游标

foreach (Flight::where('foo', 'bar')->cursor() as $flight) {
    //
}

答案 1

我们有一个比较:chunk() vs cursor()

  • 光标(): 高速
  • chunk(): 恒定的内存使用率

10,000 条记录

+-------------+-----------+------------+
|             | Time(sec) | Memory(MB) |
+-------------+-----------+------------+
| get()       |      0.17 |         22 |
| chunk(100)  |      0.38 |         10 |
| chunk(1000) |      0.17 |         12 |
| cursor()    |      0.16 |         14 |
+-------------+-----------+------------+

100,000 条记录

+--------------+------------+------------+
|              | Time(sec)  | Memory(MB) |
+--------------+------------+------------+
| get()        |        0.8 |     132    |
| chunk(100)   |       19.9 |      10    |
| chunk(1000)  |        2.3 |      12    |
| chunk(10000) |        1.1 |      34    |
| cursor()     |        0.5 |      45    |
+--------------+------------+------------+
  • TestData:Laravel 默认迁移的用户表
  • 家园 0.5.0
  • 7.0.12 菲律宾比索
  • MySQL 5.7.16
  • 拉拉维尔 5.3.22

答案 2

事实上,这个问题可能会吸引一些固执己见的答案,但是简单的答案就在Laravel Docs中。

仅供参考:

这是块:

如果需要处理数千条 Eloquent 记录,请使用该命令。该方法将检索雄辩模型的“块”,将它们提供给给定的进行处理。使用该方法将节省处理大型结果集时的内存:chunkchunkClosurechunk

这是游标:

该方法允许您使用游标循环访问数据库记录,游标将仅执行单个查询。在处理大量数据时,可以使用该方法大大减少内存使用量:cursorcursor

Chunk 从数据库中检索记录,并将其加载到内存中,同时在最后检索到的记录上设置游标,以便不会发生冲突。

因此,这里的优点是,如果要在发送大记录之前重新格式化它们,或者要每次对第n条记录执行操作,那么这很有用。例如,如果您正在构建一个 view out/excel 工作表,因此您可以对记录进行计数,直到它们完成,这样它们就不会一次加载到内存中,从而达到内存限制。

Cursor使用PHP生成器,您可以查看php生成器页面,但这里有一个有趣的标题:

生成器允许您编写使用 foreach 循环访问一组数据的代码,而无需在内存中构建数组,这可能会导致您超过内存限制,或者需要相当多的处理时间来生成。相反,您可以编写一个生成器函数,它与普通函数相同,不同之处在于生成器可以根据需要多次生成,以提供要迭代的值,而不是返回一次。

虽然我不能保证我完全理解Cursor的概念,但对于Chunk,chunk以每个记录大小运行查询,检索它,并将其传递到闭包中以进一步处理记录。

希望这是有用的。


推荐