Сравнение рельсов производительности запросов

#ruby-on-rails

#ruby-on-rails

Вопрос:

Я создаю копию Instagram. Я хочу сделать запрос, который даст мне всех пользователей, которым понравился пост. В итоге у пользователя столько сообщений, у публикации столько лайков, и у пользователя также много лайков. Это решения, которые я придумал

 def get_user_likes
    post = Post.find(params[:post_id])
    #first solution
    @user_likes =  post.likes.map(amp;:users)
    #second solution
    @user_likes = User.includes(:likes).select(:username, :id, :profile_image).where(
        likes: {post_id: params[:post_id])})
end
  

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

Спасибо!!

Комментарии:

1. Первое решение вызовет запрос n 1, поскольку вы не включаете «пользователей». Второй вариант хорош, но если вы не будете использовать Like объекты, которые вы можете использовать joins вместо includes , чтобы подобные объекты не загружались в память.

Ответ №1:

Как и в комментарии Мехмета, второе решение лучше. Я немного расширю комментарий, первое решение легко понять, но будет вызывать запрос для каждого подобного на карте, эти проблемы обычно известны как n 1 запросов.

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

Лучшим решением является объединение, во-первых, потому что оно будет выполнять на один запрос меньше, а во-вторых, потому что вернет именно то, что вы, поэтому просто замените ваши включения на join, и все готово:

 def user_likes
  @user_likes = User.joins(:likes).select(:username, :id, :profile_image).where(likes: {post_id: params[:post_id])})
end
  

Я мог бы изучить больше, но ответом будет сообщение в блоге, и я могу порекомендовать сообщение в блоге для вас:
https://semaphoreci.com/blog/2017/08/09/faster-rails-eliminating-n-plus-one-queries.html