ruby + sqlite でinsertのベンチマークをとってみた part1
まずは結果から。
- standard insertはtransaction有りのinsertをexecuteで実行
- w/o trはトランザクションなし
- execute2はinsertを実行する際のメソッドにexecute2を適用
- batchはinsertを実行する際のメソッドにbatchを適用
- loop_countはループした回数
- loop_count を上げる毎に、遅い処理は飛ばしました。
>loop_count = 100 user system total real standard insert 0.016000 0.000000 0.016000 ( 0.246619) standard insert w/o tr 0.063000 0.484000 0.547000 ( 19.855588) execute2 insert 0.016000 0.000000 0.016000 ( 0.261787) execute2 insert w/o tr 0.062000 0.328000 0.390000 ( 21.331330) batch insert 0.032000 0.000000 0.032000 ( 0.307304) batch insert w/o tr 0.078000 0.344000 0.422000 ( 22.041804) >loop_count = 1000 user system total real standard insert 0.094000 0.000000 0.094000 ( 0.361945) execute2 insert 0.062000 0.000000 0.062000 ( 0.340452) batch insert 1.656000 0.172000 1.828000 ( 2.046856) >loop_count = 100000 user system total real standard insert 7.734000 0.250000 7.984000 ( 8.557611) execute2 insert 6.829000 0.094000 6.923000 ( 7.390702)
これを見ると、トランザクション無しの実行はほぼありえないです。100倍くらい速度が違うことになります。
executeとexecute2の違いは10%くらい、execute2が早いという結果になりました。
ちなみに、execute2がなんなのかは、なかなかいい資料に出会えなくてわかってません。ごめんなさい><
ベンチマークとは関係ないですが、今回100Kのレコードを流し込んだDBのサイズはvacuum後で、5,793KBでした。
一応ソースも載せておきます。
require 'benchmark' require 'rubygems' require 'sqlite3' db = SQLite3::Database.new("Inventory.db") #使える型は、NULL、INTEGER、REAL、TEXT、BLOB db.execute(<<EOS CREATE TABLE IF NOT EXISTS Item ( ID INTEGER PRIMARY KEY AUTOINCREMENT, Code INTEGER UNIQUE NOT NULL, Name TEXT NOT NULL, Date TEXT NOT NULL ); EOS ) loop_count = 100 insert_code = [] loop_count.times{ insert_code.push((0...20).map{ ('A'..'Z').to_a[rand(26)] }.join) } db.execute("delete from Item") Benchmark.bm(30) do |x| #standard insert with transaction x.report('standard insert'){ db.transaction loop_count.times{|i| db.execute("INSERT INTO Item (Code, Name, Date) VALUES (#{i}, '#{insert_code[i]}', '2014-08-03')") } db.commit } db.execute("DELETE FROM Item") #standard insert x.report('standard insert w/o tr'){ loop_count.times{|i| db.execute("INSERT INTO Item (Code, Name, Date) VALUES (#{i}, '#{insert_code[i]}', '2014-08-03')") } } db.execute("DELETE FROM Item") #execute2 insert with transaction x.report('execute2 insert'){ db.transaction loop_count.times{|i| db.execute2("INSERT INTO Item (Code, Name, Date) VALUES (#{i}, '#{insert_code[i]}', '2014-08-03')") } db.commit } db.execute("DELETE FROM Item") #exexute2 insert without transaction x.report('execute2 insert w/o tr'){ loop_count.times{|i| db.execute2("INSERT INTO Item (Code, Name, Date) VALUES (#{i}, '#{insert_code[i]}', '2014-08-03')") } } db.execute("DELETE FROM Item") #batch insert with transaction x.report('batch insert'){ db.transaction batch_str = "" loop_count.times{|i| batch_str <<= "INSERT INTO Item (Code, Name, Date) VALUES (#{i}, '#{insert_code[i]}', '2014-08-03');" } db.execute(batch_str) db.commit } db.execute_batch("DELETE FROM Item") #batch insert without transaction x.report('batch insert w/o tr'){ batch_str = "" loop_count.times{|i| batch_str <<= "INSERT INTO Item (Code, Name, Date) VALUES (#{i}, '#{insert_code[i]}', '2014-08-03');" } db.execute(batch_str) } db.execute_batch("DELETE FROM Item") end