タイトルはちょっと釣りっぽいかも。

たとえば配列に id が10万件位入っていて、コレを使って SQL の DELETE 文を発行してデータをパージしたい、とします。(仮にDELETEとしたけど、SELECT でも UPDATE でも一緒の話。DBの処理じゃなくても多分こういうのある)。

こういうとき、10万件一気に IN で指定すると、多分SQLが長過ぎてエラーになるし、もしエラーにならなくても遅いし、かといって 1件ずつ処理してもやっぱり遅いので、ふつうは何件かまとめて処理します。 仮に1000件毎に処理するとしましょう。

こういうとき、どうするか、というのが今日のお話。どうします?

やり方はいくつかあると思うのですが、この場合僕は splice を使います。

my @ids = ... #10万件のidの配列
while ( my @sub_ids = splice(@ids, 0, 1000) ) {
    # こうすると、@sub_ids は毎回1000件ずつ入ってくる
    $db->delete('some_table', { id => \@sub_ids }); #ORマッパーは何でも良いですけど、IN で DELETE を発行してるつもり
}

とまあこんな感じで、splice だときれいに書けるし、ベンチとっても大抵早い(らしい)です。 まー danさんのこの記事とか、ほかにも色々あるし、散々語り尽くされた話なんですけどね。

でもまあ、なんでわざわざ記事書いたか、というと、コレ知らないと独自の超絶難しいロジックを書いて何とかすることになりがちで、特に頭のいい人が書いたコレの独自ロジックは 僕の理解を遥かに超える難解なコードになってしまって、間違いなく死人を出すレベルなので、そういうの避けたいよねー、というただそれだけの話。

知っていればきれいに書ける処理を、わざわざ難解なロジックで書くのは良く無いですからね、出来るだけ多くの人に知ってほしい次第。



blog comments powered by Disqus