Performance optimizations with Doctrine

In Symfony (or plain PHP) projects Doctrine allows you to focus on domain concepts and implement application use cases quickly, letting the library generate both write and read SQL queries.

Lazy loading

One of the mechanisms used by Doctrine is lazy loading. When we access, for the first time, an association present in one of our entities, Doctrine performs, behind the scenes, the db query necessary to retrieve the data and constructs the objects referred by the association.

Scenario

To make an example, let’s assume that our domain concerns books, and that these are modeled by an entity we show an excerpt.

Optimized query

Our use case requires to retrieve a list of books, and for each of them, we will need both the author and all identifiers. We could use the findBy method of the Doctrine base repository, but to reduce the processing time we write an ad-hoc method:

Filtered associations

If, for each instance of the main entity, we are interested in a single element (or a very small number of elements) of the *-to-many association, we can rewrite the entire functionality as follows:

Partial objects deprecated

Partial objects have recently been deprecated, because usually such objects break invariants, but the use shown here does not present this problem, so Doctrine will probably provide a different syntax to achieve the same result.

Conclusions

When we need to improve performances of read queries with Doctrine, we can replace lazy loading with ad hoc queries that perform joins towards low multiplicity associations, while for higher multiplicity associations, through the use of partial, we can still make it possible to perform, in an efficient way, a single query for each table involved, regardless of the number of objects fetched.