簡體   English   中英

Ruby On Rails = 將 ActiveRecord 與具有數千或記錄的數組進行比較

[英]Ruby On Rails = Compare ActiveRecord to Array with thousands or records

我有一個包含大約 500,000 條記錄 (csv_data) 的傳入 CSV。 想將它與之前存儲在 ActiveRecord (PreviousData) 中的數據進行比較。

目前有這個,但失敗了,因為比較大型數據集需要很長時間。 我將如何優化它以處理更大的數據集?

added = csv_data.select{|item| !PreviousData.where(iden: item[:iden]).exists?}

您可以使用Enumerable#each_slice分塊進行:

exists = csv_data.each_slice(1000).map do |chunk|
  PreviousData.where(id: chunk.map { |item| item[:iden] })
              .pluck(:id)
end.flatten

這將在 CSV 文件中每 1000 行執行一個 SQL 查詢,而不是每行一個,這將產生巨大的性能差異。 您當然可以使用批量大小來調整內存消耗與數據庫查詢的數量。

如果要跟蹤當前所在的切片,也可以使用with_index

exists = csv_data.each_slice(1000).with_index.map do |chunk, index|
  puts "Importing chunk #{index}"
  PreviousData.where(id: chunk.map { |item| item[:iden] })
              .pluck(:id)
end.flatten

如果您正在做的是從 CSV 文件創建記錄,您將需要考慮使用 UPSERT(如果可用)並將創建包裝在單個事務中或執行批量 INSERT/UPSERT。

以簡單的方式,您可以嘗試這樣:

stored_idens = PreviousData.pluck(:iden)
new_records = csv_data.reject { |item| stored_idens.include?(item[:iden]) }

快樂編碼:-)

您應該准備一個要檢查的值列表,然后用一個查詢檢查所有這些值。

我假設:iden列有一個 uniq 值:

# Stores all the `:iden` values from your `csv_data` variable
idens = csv_data.map{ |item| item[:iden] }

# A single query checking that all of them are present in the PreviousData's table
PreviousData.where(iden: idens).exists?

這應該只產生一個查詢(未測試)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM