Skip to content

Instantly share code, notes, and snippets.

@miio
Created October 1, 2012 16:06
Show Gist options
  • Save miio/3812729 to your computer and use it in GitHub Desktop.
Save miio/3812729 to your computer and use it in GitHub Desktop.
test run sql timing
module BulkCheck
class Storage
@@pool = []
@@where_in = {}
@@cache = nil
def self.pool data
@@pool << data
end
def self.read
@@pool
end
def self.where symbol, val
if @@where_in[symbol].nil?
@@where_in[symbol] = []
end
@@where_in[symbol] << val
p @@where_in
end
def self.obj
if Trigger.ready?
if @@cache.nil?
p "Example: run sql!"
@@cache = Mock.get_data
@@where_in = {}
end
return @@cache
else
Trigger.next
end
end
def self.last
@@pool.last
end
end
class Trigger
@@current=0
def self.run
call_method Storage.read.first
end
def self.call_method obj
obj.bulk_check_unique
end
def self.ready?
return Storage.last == Storage.read[@@current]
end
def self.current
return @@current
end
def self.next
unless ready?
@@current+=1
call_method Storage.read[@@current]
end
end
end
class Mock
def self.get_data
return [Test.new('a'),Test.new('b')]
end
end
end
class Test
def initialize val
@val = val
end
def bulk_check_unique
BulkCheck::Storage.where :name, @val
obj = BulkCheck::Storage.obj
unless obj.nil?
p obj
obj.each do |o|
p "#{o.to_s} is #{@val}"
p o.to_s == @val
end
end
end
def to_s
@val
end
end
names = ['a','b','c','d','e','f','g']
target = []
names.each do |obj|
BulkCheck::Storage.pool Test.new obj
end
# Start
BulkCheck::Trigger.run
@miio
Copy link
Author

miio commented Oct 1, 2012

前置き
ActiveRecordのUniqueチェックの際、ご丁寧に要素1つ1つに対してバリデーションしてくれる(というか、バルクインサート使うにはgemを入れる必要がある)
あまりにも非効率なので(クエリ発行回数が無駄)、WHERE IN句を使って一度に取得したデータを元にチェックすればいいのではと思って書いてみたもの。

これはDB上のnameカラムに対してa,bというレコードが存在しているという前提で、'a','b','c','d','e','f','g'をインサートする際の事前チェックを行なってみた

@miio
Copy link
Author

miio commented Oct 1, 2012

ベンチマークしてみた。
DBアクセス1回を0.1ミリ秒として(強引すぎるけど

   user     system      total        real

"Example: run sql!"
false
false
false
false
false
false
true
0.000000 0.000000 0.000000 ( 0.010812)
true
"Example: run sql!"
false
"Example: run sql!"
false
"Example: run sql!"
false
"Example: run sql!"
false
"Example: run sql!"
false
"Example: run sql!"
false
"Example: run sql!"
0.000000 0.000000 0.000000 ( 0.077724)

DBアクセスがボトルネックであればかなり回避できそう

@miio
Copy link
Author

miio commented Oct 1, 2012

問題点:異なるwhere_inを1つのメソッド内で同居できない。

回避としては、別メソッドにすればワンちゃんあるかも?
現状だと、Storageに入っている最終要素に達するまでひたすらバリデーションメソッドを叩いているため(最終要素に達した段階で一気に値を返す仕組み)
つまり、メソッドの途中から再実行できるわけもなくry

@miio
Copy link
Author

miio commented Oct 1, 2012

補足:異なるwhere_in というのは、一旦objメソッドでオブジェクトを取得できたけど、例えばその結果を用いて新たなobjメソッドを叩いても意味が無い状態

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment