Ruby on rails 通过在RubyonRails中搜索加快查找速度

Ruby on rails 通过在RubyonRails中搜索加快查找速度,ruby-on-rails,ruby,performance,ruby-on-rails-3,sql-server-2008,Ruby On Rails,Ruby,Performance,Ruby On Rails 3,Sql Server 2008,我有一个名为Staging的表,我将excel电子表格中的所有数据放入其中,通过查找现有模型/表从中获取ID号,然后将其与当前数据库SQL Server 2008进行比较 我的代码如下: def compare require 'rubygems' require 'spreadsheet' require 'set' Spreadsheet.client_encoding = 'UTF-8' file_full_path = File.expand_path(File.join(File

我有一个名为
Staging
的表,我将excel电子表格中的所有数据放入其中,通过查找现有模型/表从中获取ID号,然后将其与当前数据库SQL Server 2008进行比较

我的代码如下:

def compare 

require 'rubygems'
require 'spreadsheet'
require 'set'

Spreadsheet.client_encoding = 'UTF-8'
file_full_path = File.expand_path(File.join(File.dirname(__FILE__), "../../SISlist.xls"))
book = Spreadsheet.open(file_full_path) #Select excel file
sheet = book.worksheet 0 #Select 1st worksheet
app,server,env = 0

for i in 1..500
  row = sheet.row(i)

    if row[0].to_s != "" # Makes sure no empty cells are saved
     row.each do |t|
     app = App.find_by_name(row[0].to_s)
     server = Server.find_by_name(row[2].to_s)
     env = Environment.find_by_code(row[3].to_s)
    end
Staging.create(:app => app.id, :server => server.id, :environment => env.id)
  end
 end
end
我现在遇到的问题是,执行这个方法需要非常长的时间(几乎20秒),而我所有其他类似的方法都不需要那么长时间

有没有加快这个过程的方法或者我的工作流程是不正确的,因此整个架构是错误的

需要帮助

以加快尝试

ActiveRecord::Base.transaction do
  500.times do |i|
    row = sheet.row(i)
    if row[0].to_s != "" # Makes sure no empty cells are saved
      app = App.find_by_name(row[0].to_s)
      server = Server.find_by_name(row[2].to_s)
      env = Environment.find_by_code(row[3].to_s)
      Staging.create(:app => app.id, :server => server.id, :environment => env.id)
     end
  end
end

另外,您是否意识到,
app,server,env=0
不会将所有值初始化为零?

如果您只有几百行,则可以尝试分三步执行:

  • 旋转电子表格以收集所有应用程序、服务器和环境名称/代码
  • 将应用程序、服务器和环境批量加载到哈希中
  • 再次旋转电子表格以执行
    暂存。创建
    调用
  • 大概是这样的:

    sets = {
        :apps         => Set.new,
        :servers      => Set.new,
        :environments => Set.new
    }
    (1 .. 500).select { |i| !sheet.row(i).to_s.empty? }.each do |i|
        sets[:apps].add(row[0].to_s)
        #...
    end
    
    # You could just pull in the ids and names here rather than whole objects too.
    sets[:apps] = Set.where(:name => sets[:apps].to_a).each_with_object({ }) { |a,h| h[a.name] = a.id }
    #...
    
    (1 .. 500).select { |i| !sheet.row(i).to_s.empty? }.each do |i|
        Staging.create(
            :app => sets[:apps][row[0].to_s],
            #...
        )
    end
    

    基本上,我猜你最大的成功是反复调用
    find\u by…
    ,而不是只调用一次。

    你可以使用@jaydel,这对RoR 3有用吗?因为上面写着2.3,所以可能会贬值?是的,看起来是这样。对不起,链接不正确。这里有一个更好的——非常感谢@jaydel,我一定会看看它的。你这么做是为了什么<代码>行。每个都做| t |
    ?哦?我以为它会初始化它们?否则我可以声明它们的存在而不初始化它们吗?我尝试了你的代码,但是我得到了一条错误消息
    调用了nil的id,它会被错误地设置为4——如果你真的想要nil的id,请使用object\u id
    。知道为什么吗?我设法让它工作了,但出现的错误是由于
    500.times do | I |
    循环造成的,但不知道为什么。不幸的是,使用
    事务
    并没有提高它的速度。还有其他想法吗?我错过了一个端点检查它应该做同样的事情。我几小时后回来,我会努力加快执行速度。你真是个天才,问题在于
    if
    语句。使用
    除非第[0]行为空?
    将速度至少提高一半。但如果性能可以进一步提高,那将是非常棒的。另外,
    500.times do
    不起作用,总是会产生错误,因此我在1..500中使用了
    for I
    注意:这个版本不做行。each--我真的认为在原始版本中,您是在为每一行读取每一列。