• Czas czytania ~5 min
  • 10.10.2023

Jako programiści, nasze wybory mogą mieć duży wpływ na wydajność i wykorzystanie pamięci przez nasze aplikacje. Laravel oferuje nam różne metody pobierania danych z baz danych, takie jak  pobiera wszystkie rekordy, chunk(), i lazy(). Ten artykuł ma na celu zbadanie tych metod, podkreślając ich unikalne cechy. Porównamy je za pomocą nieformalnych testów porównawczych, aby zrozumieć ich wpływ na zużycie pamięci i szybkość. Należy zauważyć, że te punkty odniesienia nie mają charakteru naukowego, ale powinny zapewnić użyteczny obraz porównawczy.

Szybkie podsumowanie

Method Description Eager Load Low Memory Concurrent Safe
pobiera wszystkie rekordy 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

Testy porównawcze

Należy pamiętać, że testy porównawcze użyte w tym artykule nie są naukowe i zostały przeprowadzone na systemie Laravel 8.74 i PHP 7.4.25 w systemie macOS z Laravel Valet. Wszystkie testy przeprowadzono z Laravel 8.74 i PHP 7.4.25 na macOS z Laravel Valet.

10 000 rekordów 100 000 rekordów

Method Memory Time
pobiera wszystkie rekordy 26 MB 261ms
cursor() 12 MB 460ms
lazy() 9MB 300ms
chunk() by 500 6MB 400ms

Metody

Method Memory Time
pobiera wszystkie rekordy 277 MB 2.72sec
cursor() 75 MB 5.8sec
lazy() 9MB 5.4sec
chunk() by 500 6MB 7.56sec

pobiera wszystkie rekordyMetoda pobiera wszystkie rekordy wykorzystująca funkcję fetchAll()

pobiera wszystkie rekordy

The pobiera wszystkie rekordy 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.

  • Oferuje najszybszy dostęp do danych
  • Zużywa dużo pamięci

chunk()

The chunk() method uses fetchAll() to retrieve data, similar to the pobiera wszystkie rekordy 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 pobiera wszystkie rekordy, 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 pobiera wszystkie rekordy
  • 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 pobiera wszystkie rekordy, 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 pobiera wszystkie rekordy
  • 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()

Wprowadzony w Laravel 8, metoda lazy() jest bardziej przyjazną składniowo wersją chunk(). Podobnie jak chunk(), lazy() pobiera rekordy w małych segmentach. Jednak zamiast wymagać wywołania zwrotnego, lazy() wykorzystuje generatory PHP. Powoduje to uproszczoną składnię, ponieważ zwraca LazyCollection dla Twojej wygody.

Metoda lazy() zapewnia równowagę między efektywnym wykorzystaniem pamięci a czytelnością. Podczas obsługi większych zestawów danych i wykonywania operacji obejmujących jednoczesne iterowanie i aktualizowanie rekordów można zachować lazyById() spójność danych, szczególnie podczas aktualizowania kluczy podstawowych lub obcych.

  • Efficient memory usage similar to chunk()
  • Provides a cleaner syntax due to PHP generators
  • Slower than pobiera wszystkie rekordy
  • 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()

Wniosek

As we’ve explored, Laravel offers a variety of methods for data retrieval, each with its own unique strengths and weaknesses. The pobiera wszystkie rekordy and chunk() methods, perhaps the most commonly used, offer distinct benefits. pobiera wszystkie rekordy, 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.

Rzadziej stosowana, ale nadal wydajna, metoda wyróżnia się wydajnością pamięci i równoczesnym bezpieczeństwem, cursor() mimo że jest wolniejsza i nie obsługuje chętnego ładowania. Wreszcie, nowicjusz w ekosystemie Laravel, zapewnia równowagę wydajności pamięci i prostszej chunk()składni, ale, podobnie jak cursor(), lazy()nie obsługuje chętnego ładowania i nie jest bezpieczny przy jednoczesnej zmianie danych.

Ostatecznie wybór metody powinien być podyktowany konkretnymi potrzebami aplikacji:

  • Rozmiar danych
  • Dostępna pamięć systemowa
  • Wymóg dla chętnego załadunku
  • Czy dane mogą ulec zmianie podczas operacji.

While pobiera wszystkie rekordy 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

O

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...

O autorze CrazyBoy49z
WORK EXPERIENCE
Kontakt
Ukraine, Lutsk
+380979856297