0

我在使用葡萄 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获取所有用户和各自的个人资料

@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 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 秒)

4

2 回答 2

1

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

上面的 sql 产生了 N+1 的问题,这会使性能变慢。您可以检查有关此的日志。解决问题的更好方法是使用如下所示的急切加载(如 @maxplener 和 @anothermh 所建议的)

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

有关 Eager Loading 的更多信息,您可以点击以下链接:

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

于 2019-11-13T06:12:49.903 回答
0

谢谢大家,是的,这是 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}]

于 2019-11-13T16:13:06.047 回答