Eloquent get() vs chunk() vs lazy() benchmarks
I did some unscientific benchmarks of the methods available in Laravel. Even the official documents describe the characteristics of each technique, I wanted a quick ”ballpark benchmark” of which one to choose. Take the exakt numbers with a big grain of salt, my point is to show the difference between the methods.
TL;DR
get()
– High speed, but high memory usagechunk()
– Constant but low memory usage and low speed
Tested with Laravel 8.74 and PHP 7.4.25 on macOS with Laravel Valet.
Benchmarks
10 000 records
Method | Memory | Time |
---|---|---|
get() |
26 MB | 261ms |
cursor() |
12 MB | 460ms |
lazy() |
9MB | 300ms |
chunk() by 500 |
6MB | 400ms |
100 000 records
Method | Memory | Time |
---|---|---|
get() |
277 MB | 2.72sec |
cursor() |
75 MB | 5.8sec |
lazy() |
9MB | 5.4sec |
chunk() by 500 |
6MB | 7.56sec |
Methods
get()
It employs under the hood fetchAll, which loads all records into memory. This is quick, but it takes up a lot of memory.
- The fastest
- Uses a lot of memory
cursor()
The cursor method uses fetch and loads only one record from the buffer at a time into memory. A big drawback of this method is that cursor()
cannot eager load relationships. It uses less memory but is slower because it iterates one by one. Depending on your configuration, the buffer can be stored on the PHP side or the MySQL side.
- Cannot eager load relationships
- Cannot deal with large collections, Will eventually run out of memory depending on the buffers
- Since it’s only loading one record at the time data, it will keep consistency when processing datasets that could possibly change whilst doing so.
chunk()
Uses many smaller calls of fetchAll, and tries to keep memory low by breaking a big query result into smaller queries using limit depending on the chunk size you specify. In a way, it is trying to use the benefit of both get()
and cursor()
.
- Lowest memory usage
- The slowest
- If you are iterating and updating records at the same time, use
chunkById
- Can run into issues if you are updating primary or foreign keys
lazy()
In Laravel 8, there is also lazy()
, it is similar to chunking. Essentially, it does the same as chunk()
. However, you don’t need a callback since it uses PHP generators and returns a LazyCollection, which makes the syntax is cleaner.
- Low memory usage
- Nicer syntax than
chunk()
- If you are iterating and updating records at the same time, use
lazyById