diff options
author | Andreas Brandl <abrandl@gitlab.com> | 2019-08-27 19:15:28 +0200 |
---|---|---|
committer | Andreas Brandl <abrandl@gitlab.com> | 2019-09-03 12:16:03 +0200 |
commit | 53801b1206ff9e165b30117e3c3bcf543db7ad2c (patch) | |
tree | 724b80019bb368f6f7e270209a612e32d578c756 /app/models | |
parent | f15e3efba0e0523575ce61bd80396abda94b8cec (diff) | |
download | gitlab-ce-53801b1206ff9e165b30117e3c3bcf543db7ad2c.tar.gz |
Preload routes informationab-routable-nplus1
This fixes a high frequency N+1 issue:
`RoutableActions#find_routable!` is used across many controllers to
retrieve e.g. the Project or Namespace by path. The `#find_routable!`
method calls `#ensure_canonical_path` which in turn retrieves
`#full_path` from the given Routable.
This in turn triggers a lookup on `routes`, leading to a high frequency
of these queries:
```sql
SELECT "routes".* FROM "routes" WHERE "routes"."source_id" = $1 AND
"routes"."source_type" = $2 LIMIT $3
```
This is unnecessary as we already join `routes` in
`Routable#find_by_full_path` anyways.
Diffstat (limited to 'app/models')
-rw-r--r-- | app/models/concerns/routable.rb | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/app/models/concerns/routable.rb b/app/models/concerns/routable.rb index 3a486632800..07d22641a0a 100644 --- a/app/models/concerns/routable.rb +++ b/app/models/concerns/routable.rb @@ -38,7 +38,7 @@ module Routable if Feature.enabled?(:routable_two_step_lookup) # Case sensitive match first (it's cheaper and the usual case) # If we didn't have an exact match, we perform a case insensitive search - found = joins(:route).find_by(routes: { path: path }) || where_full_path_in([path]).take + found = includes(:route).find_by(routes: { path: path }) || where_full_path_in([path]).take else order_sql = Arel.sql("(CASE WHEN routes.path = #{connection.quote(path)} THEN 0 ELSE 1 END)") found = where_full_path_in([path]).reorder(order_sql).take @@ -67,7 +67,7 @@ module Routable "(LOWER(routes.path) = LOWER(#{connection.quote(path)}))" end - joins(:route).where(wheres.join(' OR ')) + includes(:route).where(wheres.join(' OR ')).references(:routes) end # Temporary instrumentation of method calls |