Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails Rails 4:如何防止在调用Model.all之前加载所有数据库记录_Ruby On Rails_Performance - Fatal编程技术网

Ruby on rails Rails 4:如何防止在调用Model.all之前加载所有数据库记录

Ruby on rails Rails 4:如何防止在调用Model.all之前加载所有数据库记录,ruby-on-rails,performance,Ruby On Rails,Performance,我遇到了一个性能问题,处理。在筛选器之前调用所有,然后在处理模型上运行第二个查询处理有大量记录,将它们全部加载到内存中,只需对它们运行第二次查询,就会导致RAM中出现峰值,我想对此进行修复 控制器中的线路为: @filter = ProcessingFilter.new(base_collection: Processing.all, options: params[:filter]) 如您所见,Processing.all作为base\u集合param传递到这里 ProcessingFilt

我遇到了一个性能问题,
处理。在筛选器之前调用所有
,然后在
处理
模型上运行第二个查询<代码>处理有大量记录,将它们全部加载到内存中,只需对它们运行第二次查询,就会导致RAM中出现峰值,我想对此进行修复

控制器中的线路为:

@filter = ProcessingFilter.new(base_collection: Processing.all, options: params[:filter])
如您所见,
Processing.all
作为
base\u集合
param传递到这里

ProcessingFilter
然后运行:

class ProcessingFilter
  def initialize(base_collection:, options: {})
    @base_collection = base_collection
    @options = options
  end

  def collection
    @collection ||= begin
      scope = @base_collection
      if condition1
        scope = scope.joins(:another_entry).where(another_entry: {customer_id: customer_id})
      end
      if condition2
        scope = scope.where('created_at >= ?', created_at_start)
      end
      if condition3
        scope = scope.where('created_at <= ?', created_at_end)
      end
      if condition4
        scope = scope.where(number: processing_number)
      end
      scope
    end
  end
end
类处理过滤器
def初始化(基本集合:,选项:{})
@基本集合=基本集合
@选项=选项
结束
def收集
@集合| |=开始
范围=@base\u集合
如果条件1
scope=scope.joins(:另一个项目)。其中(另一个项目:{customer\u id:customer\u id})
结束
如果条件2
scope=scope.where('created_at>=?',created_at_start)
结束
如果条件3

scope=scope.where('created_at以防您不使用过滤默认的_作用域(或无论如何都要忽略默认的过滤)
处理。unscope
就可以了

顺便问一下,您目前正在使用哪个版本的rails

有关已弃用的
方法的附加链接。作用域
方法:

如果您不使用过滤默认作用域(或无论如何都要忽略默认过滤)
处理。无范围的
可以解决这个问题

顺便问一下,您目前正在使用哪个版本的rails

有关已弃用的
方法的附加链接。作用域
方法:

免责声明:这本身还不是答案,但因为太长,需要键入代码:

处理。所有
尚未将记录加载到内存中,因为记录是“延迟加载”的,因为它只返回一个
ActiveRecord\u关系
对象。只有在对其使用
数组
方法后,如
每个
第一个
最后一个
映射
,或
[]
,它是否只开始将记录从数据库实际提取到内存中

证明:

processings = Processing.all

puts processings.class
# => Processing::ActiveRecord_Relation

puts processings.first.class
#   Processing Load (2.9ms)  SELECT  "processings".* FROM "processings"  ORDER BY "processings"."id" ASC LIMIT 1
# => Processing
既然我们知道
.all
不会立即将记录加载到内存中,那么我们需要找出为什么在调用
@filter=ProcessingFilter.new(base\u collection:Processing.all,options:params[:filter])时,您的代码仍在将记录立即加载到内存中。

仅限于您显示的代码,我无法在
ProcessingFilter
类中看到任何触发将记录加载到内存中的内容(没有调用将记录加载到内存中的
Array
方法);它们都是
ActiveRecord\u Relation
对象。因此,我当前的猜测是,在两个过滤器之间的某个地方,您正在调用
Array
方法:

@filter = ProcessingFilter.new(base_collection: Processing.all, options: params[:filter])

# An Array method is called:
@filter.collection.first
如果在
rails控制台中执行此操作,则需要附加
;nil
,以防止“处理”每行调用的值,因为它会立即加载记录:

@filter = ProcessingFilter.new(base_collection: Processing.all, options: params[:filter]); nil

@filter.collection.first; nil

免责声明:这本身还不是答案,但因为太长,需要键入代码:

处理。所有
尚未将记录加载到内存中,因为记录是“延迟加载”的,因为它只返回一个
ActiveRecord\u关系
对象。只有在对其使用
数组
方法后,如
每个
第一个
最后一个
映射
,或
[]
,它是否只开始将记录从数据库实际提取到内存中

证明:

processings = Processing.all

puts processings.class
# => Processing::ActiveRecord_Relation

puts processings.first.class
#   Processing Load (2.9ms)  SELECT  "processings".* FROM "processings"  ORDER BY "processings"."id" ASC LIMIT 1
# => Processing
既然我们知道
.all
不会立即将记录加载到内存中,那么我们需要找出为什么在调用
@filter=ProcessingFilter.new(base\u collection:Processing.all,options:params[:filter])时,您的代码仍在将记录立即加载到内存中。

仅限于您显示的代码,我无法在
ProcessingFilter
类中看到任何触发将记录加载到内存中的内容(没有调用将记录加载到内存中的
Array
方法);它们都是
ActiveRecord\u Relation
对象。因此,我当前的猜测是,在两个过滤器之间的某个地方,您正在调用
Array
方法:

@filter = ProcessingFilter.new(base_collection: Processing.all, options: params[:filter])

# An Array method is called:
@filter.collection.first
如果在
rails控制台中执行此操作,则需要附加
;nil
,以防止“处理”每行调用的值,因为它会立即加载记录:

@filter = ProcessingFilter.new(base_collection: Processing.all, options: params[:filter]); nil

@filter.collection.first; nil

我会考虑将这些条件语句提取到它们自己的范围方法中,然后贬低这个<代码>处理过滤器类。看起来装饰器设计得不好。


您可以使用BaseType集合值来确定被调用的模型,然后在初始化过程中将代理调用到“代码>处理筛选器< /代码>。应为您省下一些麻烦,只需调用BaseSy收藏范围。我怀疑您是因为该用法得到了重复的查询调用。

< P>我会考虑EX。将这些条件引入各自的作用域方法,然后弃用这个
ProcessingFilter
类。它看起来像是设计得不好的装饰器


您可以使用base_collection值来确定要调用的模型,然后在初始化时将对
ProcessingFilter
的调用代理到适当的作用域。这样可以省去一些麻烦,只需调用base_collection作用域。我怀疑您会因为这种用法而收到重复的查询调用。

谢谢。我很高兴为您服务为这个项目使用Rails
4.2.6
。我并没有试图忽略默认的过滤,只是尝试在另一个模型中使用几个if语句进行SQL查询,我会