2011-12-19 3 views
2

Я работаю с ОЧЕНЬ большой базой данных mysql2 на данный момент, и хотя я проиндексировал то, что я считал правильными полями, время возврата для некоторых запросов довольно медленно.Настройка производительности базы данных Rails

У меня есть две модели, вызывающие проблемы, Comment и Commenter.

Теперь существует связь has_many между Commenter и Comment, но мой запрос зависит от нахождения имени пользователя комментария комментатора. Так что я буду работать что-то вроде этого:

c = Blog.first.comments ##this bit runs fine, I indexed the "blog_id" field on Comments 
c.collect {|c| c.commenter.username} 

Чтобы помочь с проблемами скорости, я создал индекс на commenter_id поле для модели Comment. Но он все еще работает очень медленно.

Кто-нибудь знает, что я могу сделать по-другому, что поможет увеличить скорость запроса?

ответ

0

Я понял это, используя нетерпеливые нагрузки, которая не ссылка Раскольники писали, но рельсы отливки перед ним, http://railscasts.com/episodes/22-eager-loading (все еще дал вам upvote за руль меня к ответу)

Видимо я был найден следующим образом:

b = Blog.find(:first, :include=>{:comments => :commenter}) 
b.comments.collect {|c| c.commenter.username} 

Первая строка загружает первый блог и все его отношения (и возвращает блог).Поэтому, когда я звоню во вторую строчку, все уже загружено и ждет, когда будет доступен доступ.

Что работает лучше, чем я изначально делал.

3

Индекс на commenter_id помогает, если вы хотите найти комментарии для данного commenter_id («найдите мне все комментарии joe made»).

Но когда вы делаете c.commenter, вы ищете пользователей, предположительно тот, у которого id равен commenter_id комментария. В столбце id должен быть указатель. Безошибочный способ принимать заявления фактического SQL, сгенерированные (в разработке они находятся в development.log), а также использовать объяснения на них, например

explain select * from comments where id = 12345 

Учитывая, что это очень маловероятно, что вам удалось создать таблицу без индекс на это id колонка, наиболее вероятный преступник стремится нагрузка - если пост имел 500 комментариев, то приведенный выше код будет вызывать ассоциированные пользователь один на один, и эти 500 туда и обратно в базу данных складывает

c.includes(:commenter).collect {...} 

или

c.eager_load(:commenter).collect {...} 

исправит это (приведенные выше фрагменты предполагают, что вы используете рельсы 3).

+0

Я верю eager_load и включает в себя работу только для активных отношений записи. Не массивы, а в моем сообщении c - массив. – BananaNeil

+0

Это не на самом деле - ассоциации - это отношения - вы можете определенно сделать filter_ordered_comments = some_blog.comments.where (...). Order (...) например –

2

Сбор собирает объекты ActiveRecord для каждого комментатора со всеми полями по одному. В том числе/Eager Loading загрузит их одним запросом, который поможет со скоростью, но если вы хотите получить абсолютную максимальную производительность, и вам просто нужны имена, которые вам лучше свести к SQL более прямо с чем-то на мелодию:

c   = Blog.first.comments 
user_ids = c.collect(&:commenter_id) 
usernames = Commenter.where(['commenter_id IN (?)',user_ids]).select('username').collect(&:username) 
Смежные вопросы