【问题标题】:Reduce N+1 queries in serialisation with assosiations使用关联减少序列化中的 N+1 个查询
【发布时间】:2019-11-25 13:32:39
【问题描述】:

型号:

class Audio < ActiveRecord::Base
  has_many :tests, as: :item
end

class Video < ActiveRecord::Base
  has_many :tests, as: :item
end

class Test < ActiveRecord::Base
  belongs_to :user
  belongs_to :item, polymorphic: true
end

class User < ActiveRecord::Base
  has_many :tests

  def score_for(item)
    return 0 unless tests.where(item: item).any?

    tests.where(item: item).last.score
  end
end

序列化器:

class VideoSerializer < ActiveModel::Serializer
  attributes :id, :name
  attribute(:score) { user.score_for(object) }

  def user
    instance_options[:user]
  end
end

我尝试序列化很多这样的 Video 对象,但 N+1 来了:

options = { each_serializer: VideoSerializer, user: User.last }
videos = ActiveModelSerializers::SerializableResource.new(Video.all, options).serializable_hash

如果我尝试这个,返回空数组(看起来视频没有针对该用户的测试):

options = { each_serializer: VideoSerializer, user: User.last }
videos = ActiveModelSerializers::SerializableResource.new(Video.includes(:tests).where(tests: {user: User.last}), options).serializable_hash

如何在没有 N+1 查询问题的情况下组织序列化。

【问题讨论】:

  • 我很困惑。为什么要在用户中硬编码最后一个 sn-p?如果没有针对该用户的测试,这似乎按预期工作。如果您刚刚拥有Video.include(:tests),那将急切进行负载测试。如果您还想急切加载用户,可以尝试Video.includes(tests: :user)
  • 不太清楚你的意思,但无论如何我想要为这个用户独家序列化视频。

标签: ruby-on-rails activerecord ruby-on-rails-5 active-model-serializers


【解决方案1】:

如果您使用触发另一个 SQL 查询的方法(在本例中为 where),则无法避免 N+1 查询。

当您使用where 调用关系时,方法score_for 会执行另一个查询(或2 个,这肯定需要重构)。

您可以更改此方法的一种方法是不使用关系方法,而是在已加载的关系上使用数组方法。这对内存来说效率很低,但对 DB 的负担要轻得多。

def score_for(item)
  tests.sort_by&:created_at).reverse.find { |test| test.user_id == id }&.score.to_f
end

您需要加载视频及其测试和用户。

【讨论】:

  • 有道理,但我怎么能急切地为这个用户进行负载测试。就我而言,测试表很大。
  • tests = user.tests 将为该用户加载测试。如果您也想要这些测试的视频:tests = user.tests.includes(:item).where(item: {item_type: 'Video'}) 确保您在tests, user_id 中有一个数据库索引,以使此查询高效
猜你喜欢
  • 1970-01-01
  • 2014-12-02
  • 1970-01-01
  • 2023-01-07
  • 2017-07-20
  • 2013-07-22
  • 2015-03-26
  • 1970-01-01
  • 2019-05-07
相关资源
最近更新 更多