感谢 Chris Heald @cheald 的 2009 article,向我展示了最好的方法是多行插入命令。
将以下代码添加到我的initializers/active_record.rb 文件中,将我的Model.create!(...) 调用更改为Model.import!(...),然后它就消失了。几个警告:
1) 它不验证数据。
2) 它使用 SQL INSERT 命令的形式,读起来像 ...
INSERT INTO <table> (field-1, field-2, ...)
VALUES (value-1-1, value-1-2, ...), (value-2-1, value-2-2, ...), ...`
... 这可能不是所有数据库的正确语法,但它适用于 Postgres。为您的 SQL 版本更改适当语法的代码并不难。
在我的特定情况下,使用“model.create!”将 19K+ 记录插入我的开发机器(配备 8GB RAM、2.4GHz Intel Core i5 和 SSD 的 MacBook Pro)上的一个简单表中,从 223 秒开始使用 'model.import!' 到 7.2 秒。
class ActiveRecord::Base
def self.import!(record_list)
raise ArgumentError "record_list not an Array of Hashes" unless record_list.is_a?(Array) && record_list.all? {|rec| rec.is_a? Hash }
key_list, value_list = convert_record_list(record_list)
sql = "INSERT INTO #{self.table_name} (#{key_list.join(", ")}) VALUES #{value_list.map {|rec| "(#{rec.join(", ")})" }.join(" ,")}"
self.connection.insert_sql(sql)
end
def self.convert_record_list(record_list)
key_list = record_list.map(&:keys).flatten.uniq.sort
value_list = record_list.map do |rec|
list = []
key_list.each {|key| list << ActiveRecord::Base.connection.quote(rec[key]) }
list
end
return [key_list, value_list]
end
end