• Reading time ~ 5 min
  • 10.10.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.

  • Offers the fastest data retrieval
  • Consumes a high amount of memory

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.

  • Best for memory conservation, especially with larger datasets
  • Less speedy in comparison to get()
  • Potential complications in concurrency. If you are updating the same records you are iterating over (within the chunk operation), you may run into issues.

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.

  • Effective memory usage - ideal for large datasets
  • Consistently processes datasets even when data changes during the operation
  • Slower than get()
  • Unable to handle eager loading of relationships
  • There’s a potential for memory exhaustion depending on the buffer size, particularly with extremely large collections

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.

  • Efficient memory usage similar to chunk()
  • Provides a cleaner syntax due to PHP generators
  • Slower than get()
  • Unable to handle eager loading of relationships
  • Possible concurrency Issues: If the underlying data changes during the iteration process, there might be inconsistencies in the results.
  • Suited for operations that require simultaneous iteration and updates on records, using lazyById()

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:

  • Size of your data
  • Available system memory
  • Requirement for eager loading
  • Whether the data is likely to change during the operation.

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.

Comments

No comments yet
Yurij Finiv

Yurij Finiv

Full stack

ABOUT

Professional Fullstack Developer with extensive experience in website and desktop application development. Proficient in a wide range of tools and technologies, including Bootstrap, Tailwind, HTML5, CSS3, PUG, JavaScript, Alpine.js, jQuery, PHP, MODX, and Node.js. Skilled in website development using Symfony, MODX, and Laravel. Experience: Contributed to the development and translation of MODX3 i...

About author CrazyBoy49z
WORK EXPERIENCE
Contact
Ukraine, Lutsk
+380979856297