Eloquent get() vs chunk() vs lazy() benchmarks

[Updated August 2023]

As developers, our choices can greatly impact the performance and memory usage of our applications. Laravel offers us a variety of methods for data retrieval from databases, such as get(), chunk(), and lazy(). This article aims to explore these methods, highlighting their unique characteristics. We’ll compare them using some informal benchmarks to understand their implications on memory usage and speed. Note that these benchmarks are not scientific but should provide a useful comparative view.

Quick Summary

Method Description Eager Load Low Memory Concurrent Safe
get() Fetches all records at once, fastest method. Yes No Yes
chunk() Retrieves data in small “chunks,” conserving memory. Yes Yes No
cursor() Retrieves data one record at a time, saving memory. No Yes Yes
lazy() Fetches records in small segments using PHP generators, simplifying the syntax. No Yes No

Benchmarks

Please note that the benchmarks used in this article are not scientific and were conducted on a system running Laravel 8.74 and PHP 7.4.25 on macOS with Laravel Valet. All tests were conducted with Laravel 8.74 and PHP 7.4.25 on macOS with Laravel Valet.

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()

The get() method, employing the fetchAll() function, fetches all database records in a single operation. This method offers the highest speed among the alternatives; however, it comes at the cost of significant memory consumption. Thus, it’s best-suited for scenarios where you’re working with smaller datasets and where ample memory resources are available.

chunk()

The chunk() method uses fetchAll() to retrieve data, similar to the get() method. However, instead of retrieving all records at once, it breaks the process down into smaller, manageable “chunks”. This approach dramatically reduces memory consumption, especially for larger datasets, by limiting the number of records retrieved at once based on a specified chunk size.

Despite being slower than get(), chunk() shines in scenarios where memory conservation is paramount. When performing operations that involve iterating and updating records simultaneously, consider using chunkById() to avoid potential issues, particularly when dealing with changes to primary or foreign keys.

cursor()

The cursor() method leverages PHP´s fetch() function to retrieve records from the database buffer one at a time. As a result, it uses less memory than get(), making it more efficient for handling larger datasets. However, the trade-off is speed; it’s slower due to its one-by-one record iteration. An important advantage of cursor() is its consistency in processing datasets that might be subject to change during the processing period.

lazy()

Introduced in Laravel 8, the lazy() method is a more syntax-friendly version of chunk(). Like chunk(), lazy() retrieves records in small segments. However, instead of requiring a callback, lazy() employs PHP generators. This results in a simplified syntax, as it returns a LazyCollection for your convenience.

The lazy() method strikes a balance between efficient memory use and readability. While handling larger datasets and performing operations that involve iterating and updating records simultaneously, you can use lazyById() to maintain data consistency, especially when updating primary or foreign keys.

Conclusion

As we’ve explored, Laravel offers a variety of methods for data retrieval, each with its own unique strengths and weaknesses. The get() and chunk() methods, perhaps the most commonly used, offer distinct benefits. get(), while fast and capable of eager loading, consumes substantial memory, which may limit its utility with large datasets. On the other hand, chunk() method allows for memory efficiency with larger datasets and supports eager loading, but isn’t safe for operations where data changes concurrently.

Less commonly used but still powerful, the cursor() method stands out for its memory efficiency and concurrent safety, despite being slower and lacking support for eager loading. Finally, lazy(), the newcomer to the Laravel ecosystem, provides a balance of chunk()’s memory efficiency and simpler syntax but, like cursor(), does not support eager loading and isn’t safe with concurrently changing data.

Ultimately, the choice of method should be guided by your application’s specific needs:

While get() and chunk() are popular for a reason, every method has its place, and the optimal choice always depends on the context. Equipped with an understanding of each method’s trade-offs, you’re now prepared to make an informed decision that best optimizes your application’s performance and memory usage.