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