Hi%username%!
最近、Ruby on Railsの研究を開始し、CSVファイルからMySQLテーブルにデータをインポートするタスクに直面しました。 このタスクは難しくなく、コードをかなり迅速に作成しましたが、実行中にコーヒーを注いでタバコを吸うことに驚いただけです。
-ここで何かがおかしい! 私は考えて、掘り始めました。
テスト用に、データベース内のテーブルtest_objectモデルを作成しました。
create_table:test_objects do | t |
t.column:field1 ,:整数
t.column:field2 ,:整数
t.column:field3 ,:整数
t.column:field4 ,:整数
t.column:field5 ,:整数
終わり
そして小さなスクリプトを書きました:
値= []
5000回
values.push({:field1 => rand(10000),: field2 => rand(10000),: field3 => rand(10000)、
:field4 => rand(10000),: field5 => rand(10000)})
終わり
values.each do | item |
TestObject.new(アイテム).save
終わり
ランタイム:開発環境で
最大 30秒、実稼働で最大22秒。 多すぎる...
それから私は
ar-extensionプラグインを思い出しました。これはレール上に「INSERT ... ON DUPLICATE KEY UPDATE」という形式のSQLクエリを実装するために見つけました。 単一のクエリでテーブルにデータを挿入できます。
「ar-extensions」が必要
「ar-extensions / adapters / mysql」が必要です
「ar-extensions / import / mysql」が必要です
....
objs = []
values.each do | item |
objs.push(TestObject.new(アイテム))
終わり
TestObject.import objs
ランタイム:開発環境で約14秒、本番環境で約12秒。 すでに優れていますが、それでもたくさんあります。
次に、このコード部分でActiveRecordの使用を放棄し、簡単なSQLクエリを使用することにしました
sql = ActiveRecord :: Base.connection()
values.each do | item |
sql.execute( "INSERT INTO` test_objects`(` field1`、 `field2`、` field3`、 `field4`、` field5`)
VALUES( '#{item [:field1]}'、 '#{item [:field2]}'、 '#{item [:field3]}'、 '#{item [:field4]}'、 '#{item [:field5]} ') ")
終わり
ランタイム:開発環境で約5秒、実稼働で約3.5秒。
そして、トランザクションを使用する場合
sql = ActiveRecord :: Base.connection()
sql.execute( "START TRANSACTION")
values.each do | item |
sql.execute( "INSERT INTO` test_objects`(` field1`、 `field2`、` field3`、 `field4`、` field5`)
VALUES( '#{item [:field1]}'、 '#{item [:field2]}'、 '#{item [:field3]}'、 '#{item [:field4]}'、 '#{item [:field5]} ') ")
終わり
sql.execute( "COMMIT")
ランタイム:開発環境では2秒、実稼働では0.8秒 ActiveRecordを使用するよりもはるかに高速です!
一括挿入を使用する場合(
CWNと
Venturaに感謝):
objs = []
values.each do | item |
objs.push( "( '#{item [:field1]}'、 '#{item [:field2]}'、 '#{item [:field3]}'、 '#{item [:field4]}'、 '#{item [:field5]}') ")
終わり
sql.execute( "INSERT INTO` test_objects`(` field1`、 `field2`、` field3`、 `field4`、` field5`)VALUES "+ objs.join( '、'))
実行時間:運用環境で〜0.1〜0.2秒!
結論: ActiveRecordは非常に便利なものであり、使用を拒否することは決してありませんが、幅広い機能が必要でなく、速度が重要なコードの部分では、通常のSQLクエリを使用することをお勧めします。
UPD:実稼働環境にランタイムを追加し、一括挿入を使用してテストする