В данный момент я очень запутался, потому что у меня есть два индексированных столбца в отдельных таблицах. Одна из таблиц 'users' содержит около 400 000 записей, а другая - 'posts' - около 8 000 000 записей.
Я знаю, что эти два поля проиндексированы, и я подтвердил это своей схемой:
add_index "users", ["username"], :name => "index_users_on_username", :unique => true
add_index "posts", ["tag"], :name => "index_posts_on_tag", :unique => true
Но почему-то, когда я запускаю следующее, это занимает от 10 до 13 секунд:
User.find_by_username("mickeleh")
и когда я запускаю, по сути, одно и то же для постов, это занимает меньше секунды!
Post.find_by_tag("En-SKKB67Cg")
Может кто-нибудь объяснить мне, почему это может происходить?
И / или как я могу заставить мой User.find_by_username
метод работать быстрее?
Обновление:
Я дал объяснения по каждому из звонков и получил следующее:
mysql> explain SELECT `users`.* FROM `users` WHERE (lower(username) = 'mickeleh');
+----+-------------+----------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+------+---------------+------+---------+------+--------+-------------+
| 1 | SIMPLE | users | ALL | NULL | NULL | NULL | NULL | 304548 | Using where |
+----+-------------+----------+------+---------------+------+---------+------+--------+-------------+
и
mysql> explain SELECT `posts`.* FROM `posts` WHERE `posts`.`tag` = 'En-SKKB67Cg' LIMIT 1;
+----+-------------+--------+-------+---------------------+---------------------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+-------+---------------------+---------------------+---------+-------+------+-------+
| 1 | SIMPLE | posts | const | index_posts_on_tag | index_posts_on_tag | 258 | const | 1 | |
+----+-------------+--------+-------+---------------------+---------------------+---------+-------+------+-------+
Я не уверен, как именно читать то, что было возвращено, поэтому некоторая помощь с благодарностью.
Я также создал новую миграцию для «сброса» индексов в столбце username пользователя следующим образом:
remove_index :users, :column => :username
add_index :users, :username, :unique => true
не сработало
Я только что понял еще одну вещь, которая может вызывать проблему .. В таблице пользователей есть поле, которое представляет собой сериализованный набор ... и я не думаю, что это вызовет проблему. но я думаю, что это возможно.
ФИНАЛЬНОЕ ОБНОВЛЕНИЕ
Так что, по какой-то причине, когда я был очень начинающим разработчиком RoR, я решил, что было бы неплохо заменить метод 'find_by_username' на мой собственный, который бы убедитесь, что он искал имена пользователей, игнорируя регистр.
Это было довольно нелепо ... поскольку мне фактически не нужно было изменять исходный метод, чтобы получить один и тот же ответ на запросы в разных случаях.
Таким образом, мораль этой истории не включает в себя следующий метод в любой модели ...
def self.find_by_username(name)
User.where("lower(username) = '#{name.downcase}'")[0]
end
- лицо ладони -