2013-10-28 27 views
0

這是我的導入腳本。我有大約40萬條記錄。而我的連接在插入記錄期間關閉。如何將它分割成小塊?如何將我的插頁分成更小的片段?

def extract_to_database(collection) 
    tmp  = [] 
    type  = K 
    inserts = [] 

    collection.each_with_index do |line, i| 
     _type = line.strip 
     _changed = TYPES.include? _type 

     if _changed && i > 0 
     case type 
     when K then @k << tmp 
     when F then @f << tmp 
     when FB then @f << tmp 
     when I, D 
      pharmaceutic = Pharmaceutic.find_by pzn: tmp[PZN] 
      if pharmaceutic 
      inserts.push "(#{pharmaceutic.id}, '#{tmp[UNIT]}', '#{tmp[DOSE]}')" 
      end 
     end 

     tmp = [] 
     type = _type 
     end 

     tmp << clean(line) 
    end 
    sql = "INSERT INTO pharmaceutic_dosages (`pharmaceutic_id`, `unit`, `dose`) VALUES #{inserts.join(", ")}" 
    CONN.execute sql 
    end 
+0

您面臨的實際問題是什麼? –

+0

這可能是一個X,Y問題,當你試圖解決Y可能有完全不同的,更好的和/或更有效的解決方案的時候,你正在追尋解決方案的下游路徑X,如果你願意告訴我們更多關於數據和數據庫的信息。關閉自動索引可以加速更新/插入,關閉提交併在* n *記錄之後定期提交。你說你的連接正在關閉,但是不要告訴我們是否有錯誤產生,哪些應該存在,但是不要給我們實際的文本。 –

+0

另外,在準備好使用它之前,請不要打開數據庫連接。你不會顯示你連接的時間/地點,但它被認爲是不好的形式來打開它,讓它掛起一段不確定的時間,然後最終使用它。打開的連接使用服務器上的資源,因此當您加載數據時,打開連接,立即執行您需要做的事情,然後斷開連接。 –

回答

1

您的問題中缺少很多所需的信息,特別是您正在使用的DBM,您的超時值設置爲什麼,您的代碼在哪裏打開數據庫連接,實際需要多長時間處理400,000條記錄的代碼等等。所有這些都會影響工作的成敗。

此代碼吸引了我的眼球:

sql = "INSERT INTO pharmaceutic_dosages (`pharmaceutic_id`, `unit`, `dose`) VALUES #{inserts.join(", ")}" 
CONN.execute sql 

你在哪裏打開與數據庫的連接?你爲什麼打開它然後不立即使用它?數據庫配置爲在一段時間後關閉未使用的連接,因爲連接會佔用內存和CPU時間。一旦連接,發送更新/刪除/插入,然後關閉它。如果你經常連接/關閉,你只需要一個持久的連接,這對於DBM /服務器來說也可能是一個巨大的CPU消耗。

在您計算時,不要打開然後保持連接,而要等到數據準備就緒後再打開它,然後打開並立即發送。我不知道你用這麼考慮這個僞代碼的驅動程序或DBM:

sql = "INSERT INTO pharmaceutic_dosages (`pharmaceutic_id`, `unit`, `dose`) VALUES #{inserts.join(", ")}"  
CONN = connect_to_database(...) 
CONN.execute sql 
CONN.close 

這樣做的,我懷疑你會看到超時錯誤。

0

如果連接收盤插入的記錄,爲什麼不乾脆讓腳本編寫SQL語句到一個文件,然後對數據庫運行的刀片?

所以:

  1. 生成SQL語句如上面的腳本。
  2. 將它們寫入文件(本地或S3)。
  3. 複製該文件的內容並在數據庫控制檯中運行。

看起來像這樣也可以防止OOM錯誤。

0

我前段時間有同樣的問題。我發現最好的解決方案是使用resque的後臺作業。請參閱this的答案。

我還使用resque-status向用戶顯示WIP。

相關問題