Eu tenho um método em trilhos que está fazendo algo assim:
a = Foo.new("bar")
a.save
b = Foo.new("baz")
b.save
...
x = Foo.new("123", :parent_id => a.id)
x.save
...
z = Foo.new("zxy", :parent_id => b.id)
z.save
O problema é que isso leva mais e mais tempo quanto mais entidades eu adiciono. Suspeito que seja porque ele precisa acessar o banco de dados para cada registro. Como eles estão aninhados, sei que não posso salvar os filhos antes que os pais sejam salvos, mas gostaria de salvar todos os pais de uma vez e, em seguida, todos os filhos. Seria bom fazer algo como:
a = Foo.new("bar")
b = Foo.new("baz")
...
saveall(a,b,...)
x = Foo.new("123", :parent_id => a.id)
...
z = Foo.new("zxy", :parent_id => b.id)
saveall(x,...,z)
Isso faria tudo em apenas dois acessos ao banco de dados. Existe uma maneira fácil de fazer isso em trilhos ou estou preso fazendo um de cada vez?
fonte
ActiveRecord::Base.transaction { records.each(&:save) }
ou similar você pode pelo menos colocar todos os INSERTs ou UPDATEs em uma única transação.Como você precisa realizar várias inserções, o banco de dados será acessado várias vezes. O atraso no seu caso é porque cada salvamento é feito em diferentes transações do banco de dados. Você pode reduzir a latência encerrando todas as suas operações em uma transação.
Seu método de salvamento pode ser parecido com este:
A
save
chamada no objeto pai salva os objetos filho.fonte
insert_all (Rails 6+)
Rails 6
introduziu um novo método insert_all , que insere vários registros no banco de dados em uma únicaSQL INSERT
instrução.Além disso, esse método não instancia nenhum modelo e não chama retornos de chamada ou validações do Active Record.
Assim,
é significativamente mais eficiente do que
se tudo o que você deseja fazer é inserir novos registros.
fonte
Uma das duas respostas encontradas em outro lugar: por Beerlington . Esses dois são a sua melhor aposta para o desempenho
Acho que sua melhor aposta em termos de desempenho será usar SQL e inserir várias linhas em massa por consulta. Se você puder construir uma instrução INSERT que faça algo como:
INSERT INTO foos_bars (foo_id, bar_id) VALORES (1,1), (1,2), (1,3) .... Você deve ser capaz de inserir milhares de linhas em uma única consulta. Não tentei seu método mass_habtm, mas parece que você poderia fazer algo como:
Além disso, se você estiver pesquisando Bar por "algum_atributo", certifique-se de ter esse campo indexado em seu banco de dados.
OU
Você ainda pode dar uma olhada em activerecord-import. É certo que não funciona sem um modelo, mas você pode criar um modelo apenas para a importação.
Felicidades
fonte
você precisa usar esta gema "FastInserter" -> https://github.com/joinhandshake/fast_inserter
e inserir um grande número e milhares de registros é rápido porque esta gema pula o registro ativo e usa apenas uma única consulta bruta sql
fonte
Você não precisa de uma joia para acertar o DB rapidamente e apenas uma vez!
Jackrg resolveu isso para nós: https://gist.github.com/jackrg/76ade1724 relevant16292e4e
fonte