Rails: Как мне минимизировать попадания в БД? Жесткая загрузка не применима - PullRequest
2 голосов
/ 26 июня 2009

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

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

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

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

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

Что ты думаешь?

Ответы [ 2 ]

4 голосов
/ 26 июня 2009

Вам определенно следует начать работать с кеш-системой. Есть как минимум 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")

Запрос вернет Hash, где ключом является user_id, а значением - результат count. Затем вы можете выполнить итерацию хэша вместо выполнения запроса для любой записи в представлении.

2 голосов
/ 26 июня 2009

Нет правила против перезагрузки текущего пользователя, если оно позволяет использовать активную загрузку:

user = User.find (current_user.id,: include =>: подписчики)

При условии, что это простое отношение has_many, это всего лишь 2 оператора SQL.

Теперь вы можете перебирать пользователей user.subscribeers, не создавая еще одного попадания в БД.

...