...

/

Recognizing the Problem

Recognizing the Problem

Learn about the N + 1 problem.

We'll cover the following...

N+1 problem

Anytime we resolve a schema using Ecto in both the resolver and query child values, we can quickly find ourselves stuck in what’s known as the “N + 1 problem." This makes us perform more database work than we expect and can cause unnecessary problems.

Let’s say we want to get the category for a bunch of menu items. The best way is to collect all the category_id values found within your set of menu items and then do a single SQL query for categories with those IDs. The N+1 problem happens when, instead, you do an SQL query for each individual menu item’s category. This is where the problem gets its name. There’s 1 query to get the menu items themselves, and then N queries afterward, where N is the number of menu items.

To illustrate this, let’s review how a document is executed with a naive example and see what happens. We’ll add a small piece of middleware to our schema that will print out each field that executes. To do so, we need to reorganize how we apply middleware a little so we can easily compose different options. Let’s start with the def middleware refactor:

Press + to interact
def middleware(middleware, field, object) do
middleware
|> apply(:errors, field, object)
|> apply(:get_string, field, object)
end
defp apply(middleware, :errors, _field, %{identifier: :mutation}) do
middleware ++ [Middleware.ChangesetErrors]
end
defp apply([], :get_string, field, %{identifier: :allergy_info}) do
[{Absinthe.Middleware.MapGet, to_string(field.identifier)}]
end
defp apply(middleware, _, _, _) do
middleware
end

Functionally, this is ...