Resolve "N+1 database queries on the snippets dashboard"
What does this MR do?
Also see https://gitlab.com/gitlab-org/gitlab-ce/issues/40755.
This change fixes a N+1 query problem when showing snippets in /dashboard/snippets
. It reduces the number of queries by
- Passing a
user
object instead of an email toavatar_icon
to avoid theUser#find_by_any_email
calls - Eagerly load the
author
relation along with eachSnippet
Here's how I observe the change locally with N=3
snippets:
Without the change, the database interaction wrt the user model looks like this:
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["id", 50]]
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 50]]
User Load (1.3ms) SELECT "users".* FROM (SELECT "users".* FROM "users" WHERE "users"."email" = 'abrandl@gitlab.com'
SELECT "users".* FROM "users" INNER JOIN "emails" ON "emails"."user_id" = "users"."id" WHERE "emails"."email" = 'abrandl@gitlab.com') users LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 50]]
CACHE (0.0ms) SELECT "users".* FROM (SELECT "users".* FROM "users" WHERE "users"."email" = 'abrandl@gitlab.com'
SELECT "users".* FROM "users" INNER JOIN "emails" ON "emails"."user_id" = "users"."id" WHERE "emails"."email" = 'abrandl@gitlab.com') users LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 50]]
CACHE (0.0ms) SELECT "users".* FROM (SELECT "users".* FROM "users" WHERE "users"."email" = 'abrandl@gitlab.com'
SELECT "users".* FROM "users" INNER JOIN "emails" ON "emails"."user_id" = "users"."id" WHERE "emails"."email" = 'abrandl@gitlab.com') users LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 50]]
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 50]]
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["id", 50]]
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["id", 50]]
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 50]]
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", "50"]]
Notice the N=3
calls to User#find_by_any_email
.
With this change applied, this boils down to:
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["id", 50]]
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" IN (50)
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["id", 50]]
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["id", 50]]
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 50]]
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", "50"]]
Notice that the number of calls is now unrelated to the number of snippets N
being shown.
Does this MR meet the acceptance criteria?
-
Changelog entry added, if necessary -
Documentation created/updated -
API support added -
Tests added for this feature/bug - Review
-
Has been reviewed by UX -
Has been reviewed by Frontend -
Has been reviewed by Backend -
Has been reviewed by Database
-
-
Conform by the merge request performance guides -
Conform by the style guides -
Squashed related commits together -
Internationalization required/considered -
End-to-end tests pass ( package-qa
manual pipeline job)
What are the relevant issue numbers?
Closes #40755 (closed)
Edited by Yorick Peterse