Ich habe eine Methode in Schienen, die ungefähr so funktioniert:
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
Das Problem ist, dass dies immer länger dauert, je mehr Entitäten ich hinzufüge. Ich vermute, das liegt daran, dass es für jeden Datensatz die Datenbank treffen muss. Da sie verschachtelt sind, weiß ich, dass ich die Kinder nicht retten kann, bevor die Eltern gerettet sind, aber ich möchte alle Eltern auf einmal und dann alle Kinder auf einmal retten. Es wäre schön, so etwas zu tun:
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)
Das würde alles in nur zwei Datenbanktreffern erledigen. Gibt es eine einfache Möglichkeit, dies in Schienen zu tun, oder bin ich festgefahren, es einzeln zu tun?
quelle
ActiveRecord::Base.transaction { records.each(&:save) }
oder ähnlich können Sie zumindest alle INSERTs oder UPDATEs in einer einzigen Transaktion zusammenfassen.Da Sie mehrere Einfügungen durchführen müssen, wird die Datenbank mehrmals aufgerufen. Die Verzögerung in Ihrem Fall ist darauf zurückzuführen, dass jedes Speichern in verschiedenen DB-Transaktionen erfolgt. Sie können die Latenz reduzieren, indem Sie alle Ihre Vorgänge in einer Transaktion zusammenfassen.
Ihre Speichermethode könnte folgendermaßen aussehen:
Der
save
Aufruf des übergeordneten Objekts speichert die untergeordneten Objekte.quelle
insert_all (Rails 6+)
Rails 6
führte eine neue Methode insert_all ein , die mehrere Datensätze in einer einzigenSQL INSERT
Anweisung in die Datenbank einfügt .Außerdem instanziiert diese Methode keine Modelle und ruft keine Active Record-Rückrufe oder -Validierungen auf.
So,
es ist deutlich effizienter als
Wenn Sie nur neue Datensätze einfügen möchten.
quelle
Eine der beiden Antworten, die woanders gefunden wurden: von Beerlington . Diese beiden sind die beste Wahl für die Leistung
Ich denke, Ihre beste Leistung wird darin bestehen, SQL zu verwenden und mehrere Zeilen pro Abfrage in großen Mengen einzufügen. Wenn Sie eine INSERT-Anweisung erstellen können, die Folgendes bewirkt:
INSERT INTO foos_bars (foo_id, bar_id) VALUES (1,1), (1,2), (1,3) .... Sie sollten in der Lage sein, Tausende von Zeilen in eine einzelne Abfrage einzufügen. Ich habe Ihre mass_habtm-Methode nicht ausprobiert, aber es scheint, als könnten Sie etwas tun wie:
Wenn Sie die Leiste nach "some_attribute" durchsuchen, stellen Sie außerdem sicher, dass dieses Feld in Ihrer Datenbank indiziert ist.
ODER
Vielleicht sehen Sie sich noch Activerecord-Import an. Es ist richtig, dass es ohne Modell nicht funktioniert, aber Sie können ein Modell nur für den Import erstellen.
Prost
quelle
Sie müssen dieses Juwel "FastInserter" verwenden -> https://github.com/joinhandshake/fast_inserter
Das Einfügen einer großen Anzahl und Tausender von Datensätzen ist schnell, da dieses Juwel den aktiven Datensatz überspringt und nur eine einzige SQL-Rohabfrage verwendet
quelle
Sie brauchen keinen Edelstein, um DB schnell und nur einmal zu treffen!
Jackrg hat es für uns ausgearbeitet: https://gist.github.com/jackrg/76ade1724bd816292e4e
quelle