Lazy loading i eager loading – ORM

Platformy ORM (takie jak Entity Framework i NHibernate) pozwalają nam pracować z relacyjną bazą danych przy użyciu obiektów, a relacje między tabelami reprezentowane są w obiektach jako referencje do innych obiektów albo kolekcji. Podczas pobierania danych z bazy tworzone są obiekty, z odpowiednio wypełnionymi wartościami. Systemy ORM dają nam dwa możliwe tryby pobierania danych z bazy: lazy loading i eager loading. W tym wpisie opiszę jak działają te tryby i jakie są między nimi różnice.

Jeszcze tylko w kwestii nazewnictwa – lazy loading i eager loading po polsku byłoby to leniwe ładowanie i zachłanne ładowanie, ale bardziej pasują mi wersje angielskie, których będę używał dalej w tym tekście.

Tabele i obiekty

Rozważmy bazę danych reprezentowaną przez klasy na rysunku poniżej:

BookAuthorAssociation

Składa się ona z dwóch tabel “author” i “book”. Relacja między tymi tabelami to jeden do wielu, czyli jeden autor może być przypisany do wielu książek. W klasach jest to odwzorowane za pomocą właściwości nawigacyjnych Books i Author. Dzięki tym właściwościom możemy wyświetlić listę książek napisanych przez danego autora z poziomu klasu Author i wyświetlić autora z poziomu klasy Book. Dzięki lazy loading i eager loading wartości kryjące się pod tymi właściwościami będą wypełnione, gdy ich użyjemy. Jaka jest więc między nimi różnica?

Lazy loading

Lazy loading odsuwa w czasie pobranie zależności do momentu, w którym będą one niezbędne. Oznacza to, że w momencie tworzenia obiektu klasy Book pobierane są tylko dane z tabeli “book” a wartość pola Author jest niewypełniona. W momencie kiedy odwołamy się do właściwości Author zostanie wysłane zapytanie do bazy danych w celu pobrania danych z tabeli “author” i stworzony zostanie odpowiedni obiekt.

Eager loading

Eager loading natomiast pobiera wszystkie zależności od razu w momencie tworzenia obiektu. Rozważając powyższy przykład różnica będzie taka, że w momencie tworzenia obiektu klasy Book pobrane zostaną dane z tabeli “book” i “author”. Razem z obiektem klasy Book zostanie stworzony odpowiedni obiekt klasu Author.

Podsumowanie

Lazy loading i eager loading automatycznie rozwiązują za nas zależności między obiektami/tabelami. Lazy loading generuje więcej zapytań, ale dzięki temu te zapytania powinny być prostsze i nie zaśmiecamy pamięci danymi, których w danym momencie nie potrzebujemy. Eager loading przeciwnie – ogranicza liczbę zapytań do bazy danych, ale musi przechowywać w pamięci obiekty, które mogą nie być nigdy użyte.

Rozważmy przypadek, gdy chcemy wyświetlić listę wszystkich książek wypisując jej tytuł i autora. Od razu widać, że potrzebujemy dla każdej książki wartości właściwości Author, więc powinniśmy użyć eager loading, który w jednym zapytaniu pobierze wszystkie potrzebne dane.

Przeciwnym przypadkiem, będzie wyświetlanie listy autorów bez książek, które napisali. W tym przypadku świetnie się sprawdzi lazy loading, który pobierze w jednym zapytaniu tylko dane autorów bez list książek. Tak że nie zaśmiecimy pamięci niepotrzebnymi danymi plus zapytanie tylko do jednej tabeli powinno być szybsze niż do dwóch.

Widzimy więc, że wybór odpowiedniego trybu może znacząco wpłynąć na wydajność całego systemu. Warto się więc chwilę zastanowić jak będzie używana aplikacja i dobrać do tego odpowiedni sposób działania.

W następnych wpisach pojawią się przykłady użycia i działania lazy loading i eager loading w Entity Framework i NHibernate.


Comments are closed.