0

Rails では、一度に 25000 レコードをデータベースに追加する必要があります。私もそれらを検証する必要があります。

ここに私が今持っているものがあります:

  # controller create action
  def create
    emails = params[:emails][:list].split("\r\n")
    @created_count = 0
    @rejected_count = 0

    inserts = []
    emails.each do |email|
      @email = Email.new(:email => email)
      if @email.valid?
        @created_count += 1
        inserts.push "('#{email}', '#{Date.today}', '#{Date.today}')"
      else
        @rejected_count += 1
      end
    end
    return if emails.empty?
    sql = "INSERT INTO `emails` (`email`, `updated_at`, `created_at`) VALUES #{inserts.join(", ")}"
    Email.connection.execute(sql) unless inserts.empty?
    redirect_to new_email_path, :notice => "Successfuly created #{@created_count} emails, rejected #{@rejected_count}"
  end

今は非常に遅いです。タイムアウトが原因で、そのような数のレコードを追加する方法はありません。

何か案は?私はmysqlを使用しています。

4

3 に答える 3

2

次の 3 つのことが考えられます。

  1. zdennis/activerecord-importjsuchal/activerecord-fast-importなどの適切なツールを使用できます 。問題は、あなたの例では、25000 個のオブジェクトも作成することです。検証を使用しないように activerecord-import に指示すると、新しいオブジェクトは作成されません ( activerecord-import/wiki/Benchmarks )
  2. リレーショナル データベースへの数万行のインポートは決して高速ではなく、バックグラウンド プロセスを介して非同期で行う必要があります。また、DelayedJob などのツールもあります: https://www.ruby-toolbox.com/
  3. モデルに属するコードをコントローラー(TM)の外に移動します

その後、アプリケーションのこの部分の流れを再考する必要があります。のようなコントローラ アクション内でバックグラウンド処理を使用している場合create、単純にHTTP 201, またはを返すことはできませんHTTP 200。あなたがする必要があるのは、 "quick" を返しHTTP 202 Accepted、ユーザーがリクエストのステータスを確認できる別の表現へのリンクを提供することです (成功の応答は既にありますか? 失敗したメールの数は?)。バックグラウンドで。少し複雑に聞こえるかもしれませんが、これは、そのようにすべきではないというサインです。1 回のリクエストで 25000 レコードを追加する必要があるのはなぜですか? バックグラウンドは何ですか?

于 2012-05-02T19:58:12.310 に答える
0

仕事用のレーキタスクを作成してみませんか?次のリンクはそれをかなりよく説明しています。

http://www.ultrasaurus.com/sarahblog/2009/12/creating-a-custom-rake-task/

簡単に言うと、レーキ タスクを作成したら、次の方法で作業を開始できます。

レーキメンバー:load_emails

于 2012-05-02T19:57:44.133 に答える
0

速度が問題になる場合は、別の角度から問題に取り組みます。

  • テーブルの構造をコピーするテーブルを作成しますemails。させてemails_copyください。インデックスと制約をコピーしないでください。
  • データベースの高速インポート ツールを使用して、25,000 レコードをインポートします。DB ドキュメントを参照するか、MySQL のこの回答などを参照してください。入力ファイルを準備する必要がありますが、それを行う方がはるかに高速です — データがテキスト形式または表形式で既にあると思います。
  • emails_copyテーブルを模倣するためのインデックスと制約を作成しますemails。制約違反があれば表面化します。それらを修正します。
  • テーブル内のデータを検証します。重大なエラーをチェックするには、いくつかの生の SQL ステートメントが必要になる場合があります。とにかく、非常に単純な形式以外のメールを検証する必要はありません。おそらく、インポートに使用するテキストに対してすべての検証を行うことができます。
  • insert into emails select * from emails_copy電子メールを本番テーブルに配置します。さて、自動インクリメント ID を正しく取得するために少し遊んでみるとよいでしょう。
  • プロセスが成功したことを確認したら、drop table emails_copy.
于 2012-05-02T20:28:24.153 に答える