Commit 5ce93359 authored by Yorick Peterse's avatar Yorick Peterse

Merge branch 'user-by-login-performance' into 'master'

Improve User.by_login performance

This greatly speeds up the performance of `User.by_login`. I adopted some changes from @haynes in this patch, the credits go to him for coming up with those originally.

Fixes #2341

See merge request !1545
parents c0a6836b 72f428c7
...@@ -4,6 +4,7 @@ v 8.1.0 (unreleased) ...@@ -4,6 +4,7 @@ v 8.1.0 (unreleased)
- Fix error preventing displaying of commit data for a directory with a leading dot (Stan Hu) - Fix error preventing displaying of commit data for a directory with a leading dot (Stan Hu)
- Speed up load times of issue detail pages by roughly 1.5x - Speed up load times of issue detail pages by roughly 1.5x
- Make diff file view easier to use on mobile screens (Stan Hu) - Make diff file view easier to use on mobile screens (Stan Hu)
- Improved performance of finding users by username or Email address
- Add support for creating directories from Files page (Stan Hu) - Add support for creating directories from Files page (Stan Hu)
- Allow removing of project without confirmation when JavaScript is disabled (Stan Hu) - Allow removing of project without confirmation when JavaScript is disabled (Stan Hu)
- Support filtering by "Any" milestone or issue and fix "No Milestone" and "No Label" filters (Stan Hu) - Support filtering by "Any" milestone or issue and fix "No Milestone" and "No Label" filters (Stan Hu)
......
...@@ -68,6 +68,7 @@ class User < ActiveRecord::Base ...@@ -68,6 +68,7 @@ class User < ActiveRecord::Base
include Referable include Referable
include Sortable include Sortable
include TokenAuthenticatable include TokenAuthenticatable
include CaseSensitivity
default_value_for :admin, false default_value_for :admin, false
default_value_for :can_create_group, gitlab_config.default_can_create_group default_value_for :can_create_group, gitlab_config.default_can_create_group
...@@ -273,8 +274,13 @@ class User < ActiveRecord::Base ...@@ -273,8 +274,13 @@ class User < ActiveRecord::Base
end end
def by_login(login) def by_login(login)
where('lower(username) = :value OR lower(email) = :value', return nil unless login
value: login.to_s.downcase).first
if login.include?('@'.freeze)
unscoped.iwhere(email: login).take
else
unscoped.iwhere(username: login).take
end
end end
def find_by_username!(username) def find_by_username!(username)
......
class AddUsersLowerUsernameEmailIndexes < ActiveRecord::Migration
disable_ddl_transaction!
def up
return unless Gitlab::Database.postgresql?
execute 'CREATE INDEX CONCURRENTLY index_on_users_lower_username ON users (LOWER(username));'
execute 'CREATE INDEX CONCURRENTLY index_on_users_lower_email ON users (LOWER(email));'
end
def down
return unless Gitlab::Database.postgresql?
remove_index :users, :index_on_users_lower_username
remove_index :users, :index_on_users_lower_email
end
end
require Rails.root.join('db/migrate/20151007120511_namespaces_projects_path_lower_indexes') require Rails.root.join('db/migrate/20151007120511_namespaces_projects_path_lower_indexes')
require Rails.root.join('db/migrate/20151008110232_add_users_lower_username_email_indexes')
desc 'GitLab | Sets up PostgreSQL' desc 'GitLab | Sets up PostgreSQL'
task setup_postgresql: :environment do task setup_postgresql: :environment do
NamespacesProjectsPathLowerIndexes.new.up NamespacesProjectsPathLowerIndexes.new.up
AddUsersLowerUsernameEmailIndexes.new.up
end end
...@@ -11,7 +11,9 @@ describe User, benchmark: true do ...@@ -11,7 +11,9 @@ describe User, benchmark: true do
end end
end end
let(:iterations) { 1000 } # The iteration count is based on the query taking little over 1 ms when
# using PostgreSQL.
let(:iterations) { 900 }
describe 'using a capitalized username' do describe 'using a capitalized username' do
benchmark_subject { User.by_login('Alice') } benchmark_subject { User.by_login('Alice') }
......
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