dbicでバルクインサート
1個のデータを作るcreateを100回するより、100個のデータを作るcreateを1回の方が早い。
これをバルクインサートと言う、と。
んでdbicでやるわけで。
for (1..100) { my $length = int(rand(20)) + 1; my $str = String::Random->new->randpattern('.' x $length); # ふつーにいったらこーなるわけだ # $c->model('DBIC::Word')->create({word => $str}); push @word_in,{id => $_, word => $str, created_at => $now}; } $c->model('DBIC::Word')->populate(\@word_in);
で、メソッドの中でこういうことをするわけだけど、最後の行にpopulateを書いてはいけない。
perlではブロックの最終行が戻り値になる。んでpopulateはアレイで評価されるので、最後の行に書いてしまうと100回のinsert文が実行される。
900回のinsertを走らせて、ふつーの場合とバルクインサートでの比較をば
ふつー .----------------------------------------------------------------+-----------. | Action | Time | +----------------------------------------------------------------+-----------+ | /auto | 0.006055s | | /create_dummy | 3.383838s | | /end | 0.093589s | | -> /render | 0.092346s | | -> xxx::View::TT->process | 0.087332s | '----------------------------------------------------------------+-----------' バルクインサート .----------------------------------------------------------------+-----------. | Action | Time | +----------------------------------------------------------------+-----------+ | /auto | 0.006350s | | /create_dummy | 0.324708s | | /end | 0.091025s | | -> /render | 0.090256s | | -> xxx::View::TT->process | 0.087133s | '----------------------------------------------------------------+-----------'
実に10分の1の時間で済んだ。
で、不思議なことにdatetimeオブジェクトをつっこんだらpopulateが効かない。
my $now = '2008-11-28 21:58:48'; #my $now = DateTime->now( time_zone => $time_zone );
上の場合はバルクインサートが行われ、下の場合はふつーのinsertになってしまった。
何故だ?これじゃ使い物にならん。