2009-06-26 3 views
2

Этот вопрос может быть немного конкретным, но я думаю, что это интересно и из общего pov.Rails: Как свести к минимуму удары БД здесь? Нежелательная загрузка не применима

В Rails App пользователи могут подписаться на других пользователей. Когда я показываю список пользователей, которых я должен проверить, если текущий пользователь подписался на пользователей в списке. Если он подписался, я покажу кнопку отмены подписки и наоборот.

Потому что все зависит от текущего пользователя, я не могу использовать нетерпеливую загрузку. Поэтому, когда я показываю 20 пользователей в списке, я генерирую 20 дополнительных обращений к БД, что представляется мне плохой практикой.

Я думаю о хорошем способе решить эту проблему. Лучшим решением, которое я придумал до сих пор, является загрузка идентификаторов пользователей, которых current_user подписал в сеансе во время входа в систему один раз, а затем просто проверьте каждый user.id на идентификаторы в сеансе. Но, возможно, это может привести к другим проблемам, когда пользователь подписался на многих людей. Кроме того, я не уверен, что это лучший способ загрузить все подписки, даже если пользователь никогда не будет смотреть на список пользователей во время этого сеанса.

Следующее лучшее, что мне пришло в голову, это сделать то же самое, но не во время входа в систему, а вместо этого, когда загружен список пользователей.

Как вы думаете?

ответ

4

Вам обязательно нужно начать работу с системой кеша. Есть как минимум 3 способа, которыми вы можете следовать. Вы также можете комбинировать их для повышения эффективности.

кэширование базы данных

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

Модель Кэширование

дорогие запросы могут быть кэшируются.

def find_subscribers 
    Rails.cache.fetch("find_subscribers_#{current_user}") do 
    # run the query 
    end 
end 

Посмотреть Кэширование

Вы можете также кэшировать фрагменты вида для предотвращения дорогостоящих разработок.

Вы можете начать с:

EDIT:

Вы запрос может быть оптимизирован.

ActiveRecord::Base.connection.execute("SELECT count(*) as c FROM subscribers_users WHERE user_id = #{other_user.id} AND subscriber_id = #{self.id}") 

может стать

counters = SubscribersUser.count(:conditions => { :subscriber_id => self.id }, :group => "user_id") 

Запроса возвращает хэш, где ключ является идентификатор_пользователем и значение результата подсчета.Затем вы можете перебирать хеш вместо запуска запроса для любой записи в представлении.

+0

спасибо, у меня уже есть таблица отношений, и до сих пор мой запрос не так дорог. Это просто выполненный awfull лот: ActiveRecord :: Base.connection.execute ("SELECT count (*) as c FROM subscription_users WHERE user_id = # {other_user.id} AND subscriber_id = # {self.id}") Но, как я понимаю, я должен получить всех подписчиков с ОДНОМ запросом и кэшировать результат. Верный? –

+0

Я добавил более подробную информацию в исходный ответ. –

+0

спасибо, я проверю и опубликую результат! –

2

Там нет правила против перезагрузки текущего пользователя, если это позволяет использовать жадную загрузку:

пользователя = User.find (current_user.id,: включить =>: абоненты)

прилагающегося это Простое отношение has_many - это всего лишь 2 оператора SQL.

Теперь вы можете перебирать пользователей. Подписчиков, не производя другого удара БД.