Teng::Plugin::LookupPK
Tengには機能は制限されているけれどもsingle()よりも速いlookup()が使える、Teng::Plugin::Lookupていうプラグインが付属しているのだけれども、それよりもさらに機能を制限して速くしたlookup_pk()ってのを実装してみました。
一旦Teng本体をforkしたものにコミットしてみたけど、多分独立したモジュールになると思います。
__PACKAGE__->load_plugin('LookupPK');
としてあげて
$teng->lookup_pk(user => 1); # SELECT * FROM user where id = ? LIMIT 1 [1]
のように使います。primary key名がidじゃない場合は
__PACKAGE__->load_plugin('LookupPK', {pk => 'gid'});
などのように変更できます。
制限事項は以下の通りです。
機能 | single | lookup | lookup_pk |
---|---|---|---|
FOR UPDATE | o | o | o |
selectカラムの指定 opt->{columns/+columns} |
o | o | x |
カラム名のquote | o | o | x |
複数primary key | o | o | x |
SQL::Makerを用いた複雑な条件式 | o | x | x |
また、lookup_pkではselectカラムの指定を*(アスタリスク)を使っていますのでSchemaクラスで定義したcolumnsと実際のテーブルのcolumnsが一致しない場合に結果が異なることになります。
で、ORMがこのように普通は*(アスタリスク)を使わないのがなんでなのかーというのがよくわからなくて、思いつく理由としては「schema定義からはわざと外すフィールドがある」とかぐらいしかなくてたいした理由じゃないなーということで、どなたかその理由を説明してくださるかたがいらっしゃれば嬉しいです!
追記: 2012/09/18 13:54
あー、ベンチマーク結果のせるのわすれていた
Benchmark: timing 10000 iterations of dbi, lookup, lookup_arrayref, lookup_pk, single, single_by_sql... dbi: 0.755288 wallclock secs ( 0.50 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.50 CPU) @ 20000.00/s (n=10000) lookup: 1.61698 wallclock secs ( 1.02 usr 0.00 sys + 0.00 cusr 0.00 csys = 1.02 CPU) @ 9803.92/s (n=10000) lookup_arrayref: 1.68399 wallclock secs ( 1.04 usr 0.00 sys + 0.00 cusr 0.00 csys = 1.04 CPU) @ 9615.38/s (n=10000) lookup_pk: 1.24839 wallclock secs ( 0.80 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.80 CPU) @ 12500.00/s (n=10000) single: 2.4761 wallclock secs ( 1.59 usr 0.00 sys + 0.00 cusr 0.00 csys = 1.59 CPU) @ 6289.31/s (n=10000) single_by_sql: 1.29905 wallclock secs ( 0.77 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.77 CPU) @ 12987.01/s (n=10000) Rate single lookup_arrayref lookup lookup_pk single_by_sql dbi single 6289/s -- -35% -36% -50% -52% -69% lookup_arrayref 9615/s 53% -- -2% -23% -26% -52% lookup 9804/s 56% 2% -- -22% -25% -51% lookup_pk 12500/s 99% 30% 27% -- -4% -37% single_by_sql 12987/s 106% 35% 32% 4% -- -35% dbi 20000/s 218% 108% 104% 60% 54% --
このようなかんじでsingle_by_sqlとほぼ遜色ないかんじになっております