0

我有一张名为Staging的表格,其中放置了Excel电子表格中的所有数据,通过查找现有模型/表格获取ID号码,然后比较它与当前数据库是SQL Server 2008的在Ruby on Rails中加速find_by搜索

我的代码如下:

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秒) ,当我所有其他类似的方法都没有那么长时间。

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

帮助需要

+0

您可能可以使用[批量查找](http://ryandaigle.com/articles/2009/2/23/what-s-new-in-edge-rails-batched-find) – jaydel

+0

@jaydel会与RoR 3合作?因为它说2.3,所以它可能会贬值? – omarArroum

+0

是的,它是如此。对不良链接抱歉。这里有一个更好的 - 一个伟大的[指南](http://guides.rubyonrails.org/active_record_querying.html) – jaydel

回答

1

要加快尝试

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不以零初始化所有值?

+0

哦?我认为它会初始化它们?否则我可以只声明它们的存在而不用初始化它们?尝试了你的代码,但是我得到了这个错误消息:“被调用的id为零,如果你真的想要nil的id,则使用object_id',否则会错误地为4。任何想法为什么? – omarArroum

+0

我设法让它工作,但出现的错误是由于'500.times do | i |'循环,不知道为什么。不幸的是,使用'交易'并没有提高速度。任何其他想法? – omarArroum

+0

我该怎么做?从来没有做过... – omarArroum

0

如果你只有几百行,那么你可以尝试在三个步骤做:

  1. 通过自旋电子表格来收集所有的应用程序,服务器和环境的名称/代码。
  2. 将您的应用程序,服务器和环境批量加载到散列中。
  3. 再次通过电子表格旋转以执行您的Staging.create调用。

事情是这样的:

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_by...再次,而不是仅仅做一次。