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.
This commit is contained in:
parent
0a6aaf2569
commit
24c8f42278
|
@ -235,9 +235,18 @@ class User < ActiveRecord::Base
|
|||
|
||||
# Find a User by their primary email or any associated secondary email
|
||||
def find_by_any_email(email)
|
||||
User.reorder(nil).
|
||||
where('id IN (SELECT user_id FROM emails WHERE email = :email) OR email = :email', email: email).
|
||||
take
|
||||
# Arel doesn't allow for chaining operations on union nodes, thus we have
|
||||
# to write this query by hand. See the following issue for more info:
|
||||
# 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
|
||||
|
||||
def filter(filter_name)
|
||||
|
|
Loading…
Reference in New Issue