Commit 24c8f422 authored by Yorick Peterse's avatar Yorick Peterse

Use a UNION for User.find_by_any_email

This is significantly faster than using a sub-query, at least when run
on the GitLab.com production database. The benchmarks are a lot slower
now with these changes, most likely due to PostgreSQL choosing a
different (and less efficient) plan based on the amount of data present
in the test database.

Thanks to @dlemstra for suggesting the use of a UNION.
parent 0a6aaf25
...@@ -235,9 +235,18 @@ class User < ActiveRecord::Base ...@@ -235,9 +235,18 @@ class User < ActiveRecord::Base
# Find a User by their primary email or any associated secondary email # Find a User by their primary email or any associated secondary email
def find_by_any_email(email) def find_by_any_email(email)
User.reorder(nil). # Arel doesn't allow for chaining operations on union nodes, thus we have
where('id IN (SELECT user_id FROM emails WHERE email = :email) OR email = :email', email: email). # to write this query by hand. See the following issue for more info:
take # https://github.com/rails/arel/issues/98.
sql = '(SELECT * FROM users WHERE email = :email
UNION
SELECT users.*
FROM emails
INNER JOIN users ON users.id = emails.user_id
WHERE emails.email = :email)
LIMIT 1;'
User.find_by_sql([sql, { email: email }]).first
end end
def filter(filter_name) def filter(filter_name)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment