search
LoginSignup
23

More than 3 years have passed since last update.

posted at

updated at

FactoryBotで高速に大量データを作る方法

FactoryBotで大量のデータを作りたいときどうしていますか?
FactoryBotにはcreate_listという簡単に大量データが作れる便利なメソッドがあります。
ただ、とても便利なcreate_listですがパフォーマンス観点で見ると問題があります。
この記事ではサンプルを使って挙動を確認していきます。

実行環境

Ruby: 2.6.5
Rails: 6.0.0
rspec-rails: 3.9
factory_bot_rails: 5.1.1

Models

id, name, created_at, updated_atのカラムを持ったUserモデルを使います。

db/migrate/20190914140349_create_users.rb
class CreateUsers < ActiveRecord::Migration[6.0]
  def change
    create_table :users do |t|
      t.string :name
      t.timestamps
    end
  end
end

RSpec

use create_list

ユーザー一覧を取得するリクエストスペックです。
100件のユーザーをbeforeで作成しています。

spec/requests/users_spec.rb
require 'rails_helper'

RSpec.describe UsersController, type: :request do
  describe 'GET /users' do
    let(:headers) { { 'CONTENT_TYPE': 'application/json', 'Accept': 'application/json'} }
    subject(:req) { get users_path, { headers: headers, params: {} } }

    context 'use create_list' do
      before do
        FactoryBot.create_list(:user, 100)
      end
      it 'get users' do
        req
        expect(response).to have_http_status(200)
      end
    end
  end
end

このテストを実行すると下記のように100件のinsertクエリが発行されます。
これはよろしくありませんね。

log/test.log
  User Create (1.7ms)  INSERT INTO `users` (`name`, `created_at`, `updated_at`) VALUES ('Rheba Pfannerstill', '2019-10-22 04:28:53.505465', '2019-10-22 04:28:53.505465')
  User Create (6.6ms)  INSERT INTO `users` (`name`, `created_at`, `updated_at`) VALUES ('Jacquie Schaden', '2019-10-22 04:28:53.516936', '2019-10-22 04:28:53.516936')
  --- 100件のinsert ---
  User Create (0.8ms)  INSERT INTO `users` (`name`, `created_at`, `updated_at`) VALUES ('Shawanda Raynor', '2019-10-22 04:28:53.531153', '2019-10-22 04:28:53.531153')

use build_list + import(gem activerecord-import)

上記を回避するためにcreate_listの親戚(?)build_listを使います。
activerecordに馴染んでいる人であれば名前でわかると思いますがbuild_listはオブジェクトは生成しますがsaveはしません。
saveしないのでactiverecord-importを使ってバルクインサートします。

spec/requests/users_spec.rb
context 'use build_list + import(gem activerecord-import)' do
  before do
    users = FactoryBot.build_list(:user, 100)
    User.import users
  end
  it 'get users' do
    req
    expect(response).to have_http_status(200)
  end
end

この場合は下記のように1クエリーで登録してくれます。

log/test.log
User Create Many Without Validations Or Callbacks (1.4ms)  INSERT INTO `users` (`id`,`name`,`created_at`,`updated_at`) VALUES (NULL,'Katerine Swift','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Edward Walker','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Briana Herman','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Sima Jenkins','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Veronique Padberg','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Forrest Breitenberg','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Orville Anderson','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Elvia Osinski','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Pasquale Denesik','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Harlan Cremin','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Rudy Hoeger','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Maire Rodriguez MD','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Twanna Kulas','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Twanda Stamm','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Austin Jenkins IV','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Warren Cartwright','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Bo Denesik','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Mrs. Elwood Huel','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Ms. Ashanti Robel','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Mauro Crona','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Marcelina Terry','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Normand Simonis','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Lorilee Mitchell','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Jesus O\'Conner','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Zane Schowalter','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Keenan Turner','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Patricia Schulist III','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Amal Gleichner','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Lili Grimes','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Florida Tremblay','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Troy Osinski','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Frank Tillman','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Criselda Grady','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Marisa Kirlin','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Maria Morar','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Carl Boehm','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Marcy Boyer','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Mr. Hester Wilderman','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Annmarie Ernser','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Kelsey Lebsack','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Malissa Kohler MD','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Kimbery Hammes','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Isaac Heidenreich','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Ned Collins','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Virgen Stracke','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Buford Mertz','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Bianca Hermiston IV','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Lillie Dickinson IV','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Dana Bosco','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Dr. Wilma Reichert','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Blair Kozey MD','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Carey Zboncak','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Madaline VonRueden','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Norine Walter','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Aura Murazik','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Francesco Brakus','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Dwain Weber','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Isidro Wintheiser','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Leslie Adams','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Jimmie Lubowitz MD','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Abe Parker','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Marty Skiles','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Trent Dooley','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Miss Jeromy Bahringer','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Doloris McDermott','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Manie Maggio','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Mr. Scarlet Hessel','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Ms. Ashley Marvin','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Forest Mitchell','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Kyong McClure','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Elaine Heidenreich','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Ms. Gema Fadel','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Andrea Hilll','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Wilmer Dibbert','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Forest Kulas','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Mr. Seymour Runolfsdottir','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Whitney Terry','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Noe Powlowski','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Brooke Batz','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Trent Renner','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Gus Pouros','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Jules Grimes PhD','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Micheline Dibbert','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Hayden Morar','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Ms. Deangelo Wyman','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Mignon O\'Reilly','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Rickie Franecki','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Claud Walter','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Devon Romaguera','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Edmond Romaguera PhD','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Mr. Lala Ortiz','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Reed Torphy','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Abram D\'Amore','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Mrs. Jerrod Waters','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Jovita Baumbach','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Miss Angel Beatty','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Ted Ortiz','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Mr. Layne Block','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Dewayne Donnelly','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788'),(NULL,'Syreeta Douglas IV','2019-10-22 05:08:26.131788','2019-10-22 05:08:26.131788')

use build_list + insert_all(rails >=6.0.0)

rails 6.0.0からはinsert_allというバルクインサートしてくれるメソッドが追加されたのでimportの代わりにこれを使うこともできます。
importはactiverecord-importのgemを追加する必要がありますがこの方法であれば特にgemの追加は不要です。

spec/requests/users_spec.rb
context 'use build_list + insert_all(rails >=6.0.0)' do
  before do
    users = FactoryBot.build_list(:user, 100, created_at: Time.current, updated_at: Time.current)
    # buildで生成したオブジェクトをそのままは渡せませんが
    # .attributesで渡すことができます
    User.insert_all users.map(&:attributes)
  end
  it 'get users' do
    req
    expect(response).to have_http_status(200)
  end
end

この場合も下記のように1クエリーで登録してくれます。

log/test.log
User Bulk Insert (1.4ms)  INSERT INTO `users`(`id`,`name`,`created_at`,`updated_at`) VALUES (NULL, 'Lucille Cummings', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Collette Powlowski II', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Tomas Konopelski', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Alfonzo Hettinger', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Miss Jose McCullough', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Walton Green', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Hilary Turcotte', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Weldon Schmitt DVM', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Martin Hills IV', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Ms. Royce Hudson', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Emily Jacobi Sr.', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Lonny Sporer', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Lonny Schmidt', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Marcelina Rohan', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Miss Reed Dietrich', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Mrs. Cristi Rohan', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Miss Asha Walker', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Andria Lynch', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Jarrett Emard', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Gerald Kerluke', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Mr. Alexis Lubowitz', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Clement Turner', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Elvin Harber', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Amos Schiller', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Everette Grant', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Fransisca Tremblay', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Micheal Spinka', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Mrs. Oscar Doyle', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Britt Barton', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Cherri O\'Hara', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Ulrike Fay', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Ms. Vasiliki Wehner', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Robyn Jast', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Mr. Geraldo Effertz', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Ollie Armstrong V', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Harold Baumbach', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Rosendo Marquardt DDS', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Morris Blick', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Ulysses Kshlerin', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Ms. Alonso Cole', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Roberto Lind', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Claudio Runolfsson', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Alexis Ledner', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Astrid Jenkins DVM', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Arla Padberg IV', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Abel Turner', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Branden Marks', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Lionel Moen', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Nestor Legros', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Mr. Chong Schamberger', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Ms. Carol Denesik', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Nolan Morissette DVM', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Marquis Green', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Wilford Hauck', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Michel McDermott', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Mrs. Elden Kovacek', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Bart Rohan IV', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Mel Blick', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Venus Rempel', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Miss Lilla Witting', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Sharen Nikolaus III', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Margaretta Johns', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Dr. Mallory Emard', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Jeffrey Swaniawski', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Rosanne Veum', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Kathryn Pacocha', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Herminia Moen Jr.', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Dane Thompson', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Arthur Gleason', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Tiana Bogisich', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Peggie Brekke', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Kasi Bechtelar', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'James Adams', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Windy Kshlerin', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Alonso Ortiz', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Francine Walker', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Latanya Haley MD', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Yael Stanton Jr.', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Jude Hackett', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Kathleen Mills V', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Heriberto Heathcote', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Edwardo Hilll', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Noe Bins', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Sonia Hettinger', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Lon Koss', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Elana Runolfsdottir', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Julee Hirthe', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Len Miller', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Dr. Mollie Beatty', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Janet Labadie', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Reinaldo Padberg', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Yahaira Dickens', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Miss Daphine Bergnaum', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Gerald Terry', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Mariam Senger III', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Herb Kuhlman', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Devin Russel', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Ernie Stehr', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Angel Hills MD', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895'), (NULL, 'Janeth Hintz IV', '2019-10-22 05:08:25.764863', '2019-10-22 05:08:25.764895') ON DUPLICATE KEY UPDATE `id`=`id`

テストケースのパフォーマンス比較

rspecの--profileオプションで速度を比較してみました。
当然の結果ですがバルクインサートの方が圧倒的に速いことがわかります。100件でも10倍くらい速いですね。
またinsert_allよりimportの方が少し速いこともわかりました。
発行されるクエリーの実行時間はほぼ同じなので、バルクインサートするまでの内部処理で時間がかかっているのでしょう。
insert_all(, update_all, upsert_allも)が追加されてimportは使わなくなるかなと思っていたのですが、性能差がありそうなので置き換える前に調査した方が良さそうですね(調査は本題ではないので別の機会に)。

※2019/10/24追記
import vs insert_allで計測してみたところ、バルクインサートの処理だけに絞るとinsert_allの方が速かったです。
今回のinsert_allの測定ではbuild_listで生成したオブジェクトを変換する処理も含まれていたので遅くなったと思われます。

Top 3 slowest examples (2.77 seconds, 99.2% of total time):
  UsersController GET /users use create_list get users
    2.21 seconds ./spec/requests/users_spec.rb:13
  UsersController GET /users use build_list + insert_all(rails >=6.0.0) get users
    0.3268 seconds ./spec/requests/users_spec.rb:24
  UsersController GET /users use build_list + import(gem activerecord-import) get users
    0.23456 seconds ./spec/requests/users_spec.rb:35

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
23