Rails Grape api:获取更多数据时的性能

Rails Grape api: performannce when getting more data

我在使用 grape api 时遇到了性能问题。 我有以下型号:

class Profile
   has_many :transitive_user_profiles
end

class TransitiveUserProfile < ApplicationRecord
  belongs_to :profile
  belongs_to :user
  belongs_to :client

结束

class DefaultAddress 
  belongs_to :user
end

我正在通过 rest-api 使用 grape

获取所有用户和各自的配置文件
@all_profiles =  @all_profiles || 
                TransitiveUserProfile.includes(:profile).where(
              "profile_id IN (?)", application.profile_ids)
present @users, with: Identity::V3::UserEntity, all_profiles: @all_profiles #@user = User.all - around 700 users

我写了 UserEntity class

class UserEntity < Grape::Entity
  expose :id, as: :uniqueId
  expose :trimmed_userid, as: :userId
  expose :nachname, as: :lastName
  expose :vorname, as: :firstName
  expose :is_valid, as: :isValid
  expose :is_system_user, as: :isSystemUser
  expose :email
  expose :utc_updated_at, as: :updatedAt
  expose :applications_and_profiles


  def email  
    object.default_address_email
  end

   def applications_and_profiles
    app_profiles = @all_app_profiles.where(user_id: object.id).collect{|t|  {name: t.profile.unique_id, rights: t.profile.profilrechte} }
    [{:appl_id=>"test", :profiles=>app_profiles}]
  end

 end

我遇到了问题,当我尝试获取所有用户和配置文件时需要超过 15 秒。在以下代码中面临问题(花时间获取关联对象)。

 def email  
    object.default_address_email
  end

   def applications_and_profiles
    app_profiles = @all_app_profiles.where(user_id: object.id).collect{|t|  {name: t.profile.unique_id, rights: t.profile.profilrechte} }
    [{:appl_id=>"test", :profiles=>app_profiles}]
  end 

如何高效解决(通常少于5秒)

app_profiles = @all_app_profiles.where(user_id: object.id).collect{|t| {姓名:t.profile.unique_id,权利:t.profile.profilrechte}}

上面的sql造成了N+1的问题,会导致性能变慢。您可以检查有关此的日志。解决此问题的更好方法是使用预加载,如下所示(如@max pleaner 和@anothermh 所建议)

app_profiles = @all_app_profiles.where(user_id: object.id).includes(:profile).collect{|t| {姓名:t.profile.unique_id,权利:t.profile.profilrechte}}

有关预加载的更多信息,您可以关注以下内容link:

1) https://medium.com/@codenode/10-tips-for-eager-loading-to-avoid-n-1-queries-in-rails-2bad54456a3f

2) https://blog.heroku.com/solving-n-plus-one-queries

谢谢大家,是的,这是 N+1 问题。最后我能够使用 @all_app_profiles.select {|i| i.user_id == object.id}.collect {|t| {name: t.profile.unique_id, unique_id: t.profile.unique_id, rights: t.profile.profilrechte} } 而不是 @all_app_profiles.where(user_id: object.id).collect{|t| {name: t.profile.unique_id, rights: t.profile.profilrechte} } [{:appl_id=>"test", :profiles=>app_profiles}]

来解决