RoR: производительность индексированных полей - PullRequest
2 голосов
/ 08 января 2012

В данный момент я очень запутался, потому что у меня есть два индексированных столбца в отдельных таблицах. Одна из таблиц '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

- лицо ладони -

Ответы [ 2 ]

2 голосов
/ 08 января 2012
SELECT `users`.* FROM `users` WHERE (lower(username) = 'mickeleh');

Этот запрос не использует индексы.Не можетОн извлечет каждое отдельное имя пользователя, преобразует его в нижний регистр и проверит, является ли он «mickeleh».

Решение состоит в том, чтобы убедиться, что при вводе данных в таблицу все написано в нижнем регистре, а затем вы можете получитьпрочитайте запрос lower (), и он будет использовать индекс.

Я немного знаю о RoR или о том, почему он будет генерировать запросы таким образом, поэтому я не могу вам помочь.

2 голосов
/ 08 января 2012

Я не уверен, откуда поступил вызов lower() (это запрос от проверки уникальности?), Но это помешает mysql использовать индекс, заставляя его выполнять полное сканирование таблицы, как объясняется вывод показывает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...