@sugyanさんの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を使ってるのでトランザクションなしでも大丈夫。
以下、ベンチマークに使ったコードです。