Проблема с проверкой уникальности какого-то поля в rails
Пусть в модели User у нас описана валидация для поля email
validates_uniqueness_of :email, :case_sensitive => false,
:message => i18n_proxy(:email_already_registered)
Следующий код генерирует вот такой запрос к базе данных:
SELECT * FROM users WHERE lower(email) = 'thmth' LIMIT 1
А на таблице users у нас индекс по полю email. В postgresql запрос, что вверху, не будет использовать индекс. Представьте, что будет, когда в таблице users десятки тысяч записей, а на каждое изменение любого поля в users вызывается такой запрос.
Именно это я наблюдал совсем недавно на нашей живой базе. Проблема решается
просто, например, убрать :case_sensetive
, а email всегда
предварительно переводить в нижние буквы.
Есть другой вариант, сделать функциональный индекс:
CREATE INDEX ON users(lower(email))
Беда в том, что в таком случае (а его мы тоже используем, но уже в другом проекте) придется держать 2 индекса на email - обычный и функциональный. И вот почему:
User.find_by_email 'evtuhovich@gmail.com'
Этот код выполнит в БД следующий запрос:
SELECT * FROM "users" WHERE ("users"."email" = 'evtuhovich@gmail.com') LIMIT 1
В любом случае, все зависит от решаемой задачи.