я столкнулся с проблемой производительности, используя виноградный 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 секунд)
user
вUser.all
вы вызываетеTransitiveUserProfile.all.where("profile_id=?", 12).where(user_id: object.id)
, а затем создаете экземпляры всех записей из этой коллекции, поэтому около 700+1 запросов, если я правильно понимаю) - person anothermh   schedule 13.11.2019Entity
используется для рендеринга каждой записи в@users
, поэтому для каждойuser
в@users
вы вызываете методapplications_and_profiles
; 2 - вызовModel.where
не создает экземпляры записей, поэтому ваш@all_app_profiles
не имеет записей в памяти, поэтому, когда вы, наконец, вызываете@all_app_profiles.where().collect
, ЭТО происходит, когда записи извлекаются в память, поэтому вы запускаете этот запрос один раз для каждого пользователя, следовательно это 700+1 или N+1. (и ваши журналы должны показывать это). Подробнее см. здесь. - person anothermh   schedule 13.11.2019@all_app_profiles.where(user_id: object.id).includes(:profile).collect { |t| ... }
- person max pleaner   schedule 13.11.2019