GraphQL uses resolvers in order to handle complex queries.
Due to how resolvers work however, you can accidentally create a performance problem called the N+1 query.
What is N+1 query?
Consider this innocent-looking query:
This is what the GraphQL resolver will do to resolve this query:
Query.searchProducts
resolver will be called. Once the query is resolved,Product.shop
resolver will be called for each product.
This is how the code looks like:
When the search returns 20 products, Product.shop
resolver will call the database 20 times in a short time range.
This is what we call N+1 query problem.
The number of database calls grows according to the number of previous results returned.
How Dataloader and batching can solve this problem
We already know ahead of time that Product.shop
resolver will be called multiple times with different product ids.
We can just batch the database calls to one single call with multiple product ids at once.
This is what Dataloader does.
Here’s how we can use Dataloader to solve the N+1 query problem:
And here’s how we can use the dataloader in the resolver:
How does Dataloader work?
- Dataloader is created with a batch function.
- When
dataLoader.load
is called, it will queue the request until the queue is full or some time has passed. - When the above condition is met,
dataLoader
will call the batch function with an array of keys (in this case, shop ids). - Then the dataLoader will split the array and return the requested item for each key.
This way instead of 21 database calls, we only make 2 database calls.
Where can I get these dataloader implementations?
There are many different dataloader implementations.
Popular languages and frameworks tend to have dataloaders implemented by the community.
This is an example of JavaScript implementation.
When should I use Dataloader?
Sometimes it’s hard to tell ahead of time whether a resolver will be called multiple times or not.
I tend to use Dataloader by default whenever I see a resolver requests for a single resource.
Conclusion
It is easy to create N+1 query problem in GraphQL and can happen very often.
Dataloader solves this problem by batching the database calls into a single call.
Take time to analyze your GraphQL schema and find spots where N+1 query problem can happen. Then use Dataloader to solve it.