2017-08-17 6 views
0

私は現在Ruby/Railsのプロジェクトに取り組んでいますが、データベースに請求書をインポートしていますが、実際には遅すぎるプロセスの効率を最大限にしようとしています。Ruby/Railsで大量のデータセットをインポートする作業

100.000行のインポートバッチでは、データベース内の各レコードを処理して保存するのに約2.5時間かかります。

//// Rubyはコード

class DeleteImportStrategy 
def pre_process(merchant_prefix, channel_import) 
    # channel needed to identify invoices so an import from another channel cannot collude if they had same merchant_prefix 
    Jzbackend::Invoice.where(merchant_prefix: merchant_prefix, channel: channel_import.channel).delete_all 
    # get rid of all previous import patches which becomes empty after delete_import_strategy 
    Jzbackend::Import.where.not(id: channel_import.id).where(channel: channel_import.channel).destroy_all 
end 

def process_row(row, channel_import) 
    debt_claim = Jzbackend::Invoice.new 
    debt_claim.import = channel_import 
    debt_claim.status = 'pending' 
    debt_claim.channel = channel_import.channel 
    debt_claim.merchant_prefix = row[0] 
    debt_claim.debt_claim_number = row[1] 
    debt_claim.amount = Monetize.parse(row[2]) 
    debt_claim.print_date = row[3] 
    debt_claim.first_name = row.try(:[], 4) 
    debt_claim.last_name = row.try(:[], 5) 
    debt_claim.address = row.try(:[], 6) 
    debt_claim.postal_code = row.try(:[], 7) 
    debt_claim.city = row.try(:[], 8) 
    debt_claim.save 
end 

エンド

CSVとして入ってきた各インポートのバッチのためのそう////

は、私が以前のバッチとスタートを取り除きます各行を読み込み、新しいインボイスとしてインポートレコードに挿入して、新しい行をインポートします。しかし、100.000のエントリのための2.5-3時間は少し過度のようです。どのようにしてこのプロセスを最適化できますか?確かにこの方法では効率的ではないと確信しています。

編集: 私はこの記事を投稿して以来、長いことがありましたが、ちょうど注意する必要があります。それ以来、私はactiverecord-importライブラリを使用しました。ただし、on_duplicate_key_update機能はPostgreSQL v9.5 +でのみ利用可能です。

答えて

2

大量インポートの最初のルール:バッチ、バッチ、バッチ。

各行を別々に保存しています。これは大きなオーバーヘッドを招く。つまり、インサート自体には1msがかかりますが、データベースへのラウンドトリップは5msです。使用された合計時間 - 6ms。 6000msまたは6秒の1000レコードです。

ここで、同じステートメントの複数行のデータを送信する一括挿入を使用するとします。

INSERT INTO users (name, age) 
VALUES ('Joe', 20), ('Moe', 22), ('Bob', 33'), ... 

たとえば、この1回のリクエストで1000行分のデータを送信するとします。要求自体には1000ミリ秒かかります(実際には、クエリーの解析、実行計画の準備など、かなり高速になります)。取られた合計時間は1000ms + 5msです。少なくとも6倍の削減! (私の実際のプロジェクトでは、私は100x-200xの削減を観察していました)。

+0

ありがとうございました!上記のpre_processメソッドで持っている以前のレコードを削除するのはどうですか?私は同じ方法でそれに接近すべきでしょうか? –

+0

@SahilGadimbayli:うん、それらもバッチ削除してください。単一の 'DELETE FROM users'がその仕事をしますが、仕事を長時間ブロックするかもしれません。その場合、より小さなバッチで削除してください。 –

+0

あなたはhttps://github.com/jamis/bulk_insert gemに興味があるかもしれません。 –

関連する問題