Рельсы создают одну запись VS создают несколько записей разница в производительности - PullRequest
0 голосов
/ 10 апреля 2019

Есть ли разница в скорости между этими методами?(POSTGRESQL)

Первый

products = [{...},{...},...]
products.each { |p|
  Product.create(p)
}

Второй

products = [{...},{...},...]
Product.create(products)

Оба метода для каждой записи выполняют два запроса:

1) INSERT INTO "products" VALUES (..)
2) UPDATE "products" SET "updated_at"...

Ответы [ 2 ]

1 голос
/ 10 апреля 2019

Не должно быть никакой разницы с точки зрения производительности между ними.

Если вы проверите реализацию , вы увидите, что если вы передадите массив в .create, он будет перебирать массив и вызывать .create для каждого элемента в массиве.

module ActiveRecord
  module Persistence
    extend ActiveSupport::Concern
    module ClassMethods
      # ...
      def create(attributes = nil, &block)
        if attributes.is_a?(Array)
          attributes.collect { |attr| create(attr, &block) }
        else
          object = new(attributes, &block)
          object.save
          object
        end
      end
      # ...
   end
end

ActiveRecord фактически не реализует массовые вставки. Под этим я подразумеваю вставку нескольких строк в один оператор:

INSERT INTO products (name, description) VALUES ('Soap', '100% whale based.'),('Shampoo', '...') 

Что может быть быстрее на порядок при достаточном количестве записей.

Но вы можете написать собственный SQL для этого:

class Product
  def self.mass_insert(attributes)
    values = products.map("(#{attributes[:name]}, #{attributes[:description]})").join(',')
    self.connection.execute("INSERT INTO products (name, description) VALUES #{values}")
  end
end

Обратите внимание, что этот простой пример НЕ очищает входные данные и уязвим для атаки SQL-инъекцией.

0 голосов
/ 10 апреля 2019

макс. верно.Это локальное решение.

Но я обнаружил activerecord-import gem , который делает то же самое - массовый импорт объектов.

...