かみぽわーる

kamipo's blog

SQLでincrementした値を表示するやつ

MacBook Air 11インチ欲しい!

@さんのSQLでincrementした値を表示する方法を考える - すぎゃーんメモを生DBIでやってみたのとベンチマークとってみた。

トランザクションなし

       Rate  dbic  teng  dbi1  dbi2
dbic  578/s    --  -64%  -92%  -92%
teng 1587/s  175%    --  -78%  -79%
dbi1 7143/s 1136%  350%    --   -7%
dbi2 7692/s 1231%  385%    8%    --

トランザクションあり

       Rate  dbic  teng  dbi1  dbi2
dbic  581/s    --  -59%  -88%  -92%
teng 1429/s  146%    --  -71%  -81%
dbi1 5000/s  760%  250%    --  -35%
dbi2 7692/s 1223%  438%   54%    --

DBIC遅いお…。

一応、DBICもTengも発行されるクエリが少なくなるように書いてみたけど生DBIとは結構差が出ましたね。

DBIのクエリのほうをすこし説明すると、dbi1のほうがUPDATEしようとして出来なかったらINSERT、dbi2がINSERTしようとして出来なかったらUPDATEするクエリです。

DBICとTengで使ってるfind_or_createメソッドはSELECTしてレコードがなかったらINSERTするんですが、こういうユースケースでSELECTしてレコードがないのは最初の一回だけで、二回目以降は存在してるに決まってるレコードに対していきなりUPDATEすればいいと思います。

今回のユースケースはincrementしたあとに表示するってのがあるのでSELECTしたのを再利用できるんですけど、これがincrementだけして表示しなくていいだと毎回しなくてもいいSELECTが走ることになります。

そこでDBICにあるupdate_or_createメソッドを使えばよさそうだと思ったんですけど、これもSELECTしてレコードなければINSERTしてあったらUPDATEするんですよ。update_or_createメソッドっているの?

あと実用上、dbi2以外はトランザクションありじゃないと更新が競合する可能性があります。dbi2はMySQLのINSERT ... ON DUPLICATE KEY UPDATE構文を使って一回のクエリで更新してるのでトランザクションなしでも大丈夫。pageviewの取得もLAST_INSERT_IDを使ってるのでトランザクションなしでも大丈夫。

以下、ベンチマークに使ったコードです。