У меня такая же проблема. Я разбор больших таблиц и схемы, используемых для хранения данных вложен, поэтому я вставив только один «Sinbad
», но тысячи «Pinbad
» может получить вставлены сразу ...
Что я придумал чтобы ускорить вставку, чтобы навалом вставить нижние листья схемы (визуализировать схему как дерево), так как это должна быть модель с наибольшим количеством экземпляров для создания - в вашем случае экземпляров Pinbad. Мы не можем вставлять средние листовые материалы, поскольку объемная вставка не позволяет извлекать идентификаторы вставленных множительных моделей (см. Обсуждение here относительно postgresql, например). Так что это не идеально, но это единственный способ сделать вставки более эффективными (без изменения самой схемы).
Вы должны удалить accepts_nested_attributes_for
, как вам нужно, чтобы сохранить объекты на себя, и это удобно использовать activerecord-import для массовой вставки:
class Sinbad
#
# Let's imagine you still receive the params as if you were using accepts_nested_attributes,
# Meaning :pinbads_attributes will be nested under :tinbads_attributes
# that will be nested under :sinbad
#
def self.efficient_create params
# I think AR doesn't like when attributes doesn't exist,
# so we should keep the tinbads attributes somewhere else
tinbads_attributes = params[:tinbads_attributes]
params.delete :tinbads_attributes
sinbad = self.create! params
# Array that will contain the attributes of the pinbads to bulk insert
pinbads_to_save = []
# ActiveRecords-Import needs to know which cols of Pinbad you insert
pinbads_cols = [:tinbad_id, :name, :other]
# We need to manually save the tinbads one by one,
# but that's what happen when using accepts_nested_attributes_for
tinbads_attributes.each do |attrs|
pinbads_attribute = attrs[:pinbads_attributes]
attrs.delete :pinbads_attibutes
tinbad = sinbad.tinbads.create! attrs
pinbads_attributes.each do |p_attrs|
# Take care to put the attributes
# in the same order than the pinbad_cols array
pinbads_to_save << [tinbad.id, p_attrs[:name], p_attrs[:other]]
end
end
# Now we can bulk insert the pinbads, using activerecord-import
Pinbad.import_without_validations_or_callbacks pinbad_cols, pinbads_to_save
end
end
Вот что я сделал в моей ситуации и как последний уровень в иерархии схемы имеет наибольшее количество экземпляров для создания, общее время вставки значительно сократилось. В вашем случае вы замените ~ 400 вставок Pinbad на 1 объемную вставку.
Надеюсь, что это поможет, и я открыт для любого предложения или альтернативного решения!
Вы пытались использовать массив вложенных хэшей? я думаю, что он должен работать до тех пор, пока веб-сервер поддерживает этот объем данных, отправленных в почтовом запросе –
@MohammadAbuShady, я не уверен, что понимаю. Я создаю только один «Sinbad» в контроллере, но активная запись генерирует отдельный «insert» для каждого вложенного атрибута и рекурсивно генерирует инструкцию insert для вложенных атрибутов этого атрибута. – adam2012
хорошо не так логично, это разные таблицы –