Lazy Loading vs Eagerly Loading
An ORM concept
Lazy Loading:
In object relational mapping, a “lazy load” refers to an attribute that does not contain its database-side value for some period of time, typically when the object is first loaded. Instead, the attribute receives a memoization that causes it to go out to the database and load its data when it’s first used. Using this pattern, the complexity and time spent within object fetches can sometimes be reduced, in that attributes for related tables don’t need to be addressed immediately.
Lazy loading is the opposite of eager loading.
This topic becomes more interesting when i got error while working with `SQLAlchemy`, the error is:
Parent instance <x> is not bound to a Session; (lazy load/deferred load/refresh/etc.) operation cannot proceed
the reason for this error is described as below:
This is likely the most common error message when dealing with the ORM, and it occurs as a result of the nature of a technique the ORM makes wide use of known as lazy loading. Lazy loading is a common object-relational pattern whereby an object that’s persisted by the ORM maintains a proxy to the database itself, such that when various attributes upon the object are accessed, their value may be retrieved from the database lazily. The advantage to this approach is that objects can be retrieved from the db without having to load all of their attributes or related data at once, and instead only that data which is requested can be delivered at that time. The major disadvantage is basically a mirror image of the advantage, which is that if lots of objects are being loaded which are known to require a certain set of data in all cases, it is wasteful to load that additional data piecemeal.
Another caveat of lazy loading beyond the usual efficiency concerns is that in order for lazy loading to proceed, the object has to remain associated with a Session in order to be able to retrieve its state. This error message means that an object has become de-associated with its
Session
and is being asked to lazy load data from the database.The most common reason that objects become detached from their
Session
is that the session itself was closed, typically via theSession.close()
method. The objects will then live on to be accessed further, very often within web applications where they are delivered to a server-side templating engine and are asked for further attributes which they cannot load.Within SQLAlchemy, lazy loading is a key feature of the ORM, and applies to attributes which are mapped on a user-defined class. When attributes that refer to db columns or related objects are accessed, for which no loaded value is present, the ORM makes use of the
Session
for which the current object is associated with in the persistent state, and emits a SELECT statement on the current transaction, starting a new transaction if one was not in progress. If the object is in the detached state and not associated with anySession
, this is considered to be an error state and an informative exception is raised.
Techniques to handle error:
- Try not to have detached objects; don’t close the session prematurely — Often, app will close out a transaction before passing off related objects to some other system which then fails due to this error. Sometimes the transaction doesn’t need to be closed so soon; an example is the web application closes out the transaction before the view is rendered. This is often done in the name of “correctness”, but may be seen as a mis-application of “encapsulation”, as this term refers to code organization, not actual actions. The template that uses an ORM object is making use of the proxy pattern which keeps database logic encapsulated from the caller. If the
Session
can be held open until the lifespan of the objects are done, this is the best approach. - Otherwise, load everything that’s needed up front — It is very often impossible to keep the transaction open, especially in more complex applications that need to pass objects off to other systems that can’t run in the same context even though they’re in the same process. In this case, the application should prepare to deal with detached objects, and should try to make appropriate use of eager loading to ensure that objects have what they need up front.
- And importantly, set expire_on_commit to False — When using detached objects, the most common reason objects need to re-load data is because they were expired from the last call to
Session.commit()
. This expiration should not be used when dealing with detached objects; so theSession.expire_on_commit
parameter be set toFalse
. By preventing the objects from becoming expired outside of the transaction, the data which was loaded will remain present and will not incur additional lazy loads when that data is accessed. Note also thatSession.rollback()
method unconditionally expires all contents in theSession
and should also be avoided in non-error scenarios.
Eagerly Load:
If attributes that is populated with its database-side value at the same time as when the object itself is loaded from the db. In SQLAlchemy, the term “eager loading” usually refers to related collections and instances of objects that are linked between mappings using the relationship()
construct, but can also refer to additional column attributes being loaded, often from other tables related to a particular table being queried, such as when using inheritance mappings.