遅い原因がやっとわかった

結論からいうとs2dao.netの最新版では問題ない。


複数行取得する際にカラム情報をキャッシュすることでパフォーマンスを向上させる
https://www.seasar.org/issues/browse/DAONET-34


原因がわかるまで一日かかってしまった。


昔作ったseasar.net 1.2.2.0, s2dao.net 0.4.5のシステムでレポートをCSV形式でだすというのがあった。
最初のうちはレポートの件数自体がすくなかったので特に問題がなかった。


でも件数が増えた場合(たとえば5万件)とかにした場合にどうなるか考えて見た。
まず思ったのはリフレクションがおそいだろうと。
なのでSQLで文字列をくみたてて、ひとつのプロパティにマップする。
あとは分割してもってきて、分割でCSVをかきだせばいいんじゃないかと。
まあ、データに,とか"が入っていたときにどうするのかという問題が残るがまあ方式としてはこれでいいだろうと。。。


まず今のままで5万件のデータでどうなるのか調べてもらったら6分以上かかった(Daoのメソッド呼び出しの時間)。orz
同僚に相談したら、いくらリフレクションを遅いといってそんなに遅いはずはないだろうと。
なのでVisual Studioでプロファイルをとってみることにした。


初Webでのプロファイル。まず早速はまる。プロファイルが取れない。


Unit Testing Web Applications in VSTS
http://blogs.advantaje.com/blog/kevin/Net/2006/03/02/Unit-Testing-Web-Applications-in-VSTS.html?page=comments
によると、こいつをWeb.configに追加する必要があった。

<location path="VSEnterpriseHelper.axd">
  <system.web>
    <authorization>
      <allow users="*"/>
    </authorization>
  </system.web>
</location>

やっとプロファイルがとれたがみてもわかんねー。


結局、デバッグのステップ実行でソースを追ってみた。
そうしたら不思議な現象に。。。。
外だしSQLでAのテーブルにしかマッチングさせてないのにEntityにRELNOが指定されている結合先のBのテーブルがnewされキーだけInjectionされる。
マッピングさせたい場合ってselectの戻りのコラム名をxxx_数字にしないとマッピングされないじゃないだっけ?


本間君にきいたら昔はそういう仕様。
[Seasar-user:3605] [S2Dao]RELNO設定時の“結合なしSQLの結果”の仕様について
http://ml.seasar.org/archives/seasar-user/2006-May/005519.html


ひがさんがこたえている

SQLアノテーション、もしくはSQLファイルがあるときに、
SQLに関連エンティティの記述がない場合には、
関連エンティティの処理はしないという風に
仕様を変えても良いのではないかと思います。

特にこのMLで反対がなければ、nullを返すようにしましょう。

s2daoの最新では直っている。s2dao.netでは仕様変更はされていない。
これはでもまた別の問題。たしかに無駄なnewとリフレクションがはしることになるが。。。


結局シンプルなテストコードを作って測定することに。
5万件、1テーブル50プロパティ(Stringのみと一番コストがたかそうなNullableDateTimeのみのやつ。特にちがいはなかった)。
結合先にテーブルを二つ。こいつはidのみ。


5万件データのinsertのSQLをgroovyで作成してosqlからながしたらOut Of Memoryでインサートされず。
Management Studio Expressにコピペーして実行も途中でおちてしまう。
うーん、GroovySQLをマスターしておくべきだった(SQL ServerJDBCドライバーの設定がめんどくさいので放置していた)。
結局s2dao.netでinsert(int id)みたいな外だしSQLをループでまわしていれることに。
insertはできるのだがなぜかReshaperからはエラーがあがってくる(件数すくない場合はエラーにはならない)。
とりあえず放置。


でやっとうごかせるようになった。10秒でかえってきた。ちなみに1万件の場合は1秒だった。

DEBUG 2007-02-11 11:34:48,432 [8]
select TOP 50000 * from Basic
DEBUG 2007-02-11 11:34:58,677 [8]

2テーブルを結合先にふくめたら確かに遅くはなるが15秒でかえってきた。

DEBUG 2007-02-11 11:36:19,523 [8]
SELECT TOP (50000) * FROM Basic
DEBUG 2007-02-11 11:36:34,765 [8]


なにかがおかしい。。。。
s2dao.netではなくてアプリ側か?でもソース見た限りそんなはずはない。


で気がついた(うーん、ぼけてた)。
この検証のテストコードは現在のseasar.netとs2dao.netの最新だ。
バージョンあわせないと意味ないジャンと。


なのでテストコードのブランチきって昔のバージョンで実行。
がーん、昔のバージョンってIListに対応してないのか。。。。
コードを修正。実行。


やっとおそくなった。

DEBUG 2007-02-11 13:57:56,386 [8]
select TOP 50000 * from Basic
DEBUG 2007-02-11 14:02:21,377 [8]


さてどうしたものかと更新履歴をみたがなぜかS2Container.NET 1.1.0からしかかかれていない。
https://www.seasar.org/svn/s2container.net/trunk/s2container.net/Changes.2005.txt


なのでjiraをみにいった。そのものずばりのものが。。。これか。。。最初からこいつを見るべきだったな。


複数行取得する際にカラム情報をキャッシュすることでパフォーマンスを向上させる。
https://www.seasar.org/issues/browse/DAONET-34
http://d.hatena.ne.jp/akiramei/20061102/p1


s2dao.net 1.0.1では直っている。
かなり遠回りしてしまった。


バージョンごとの検証環境を作っておくのはオープンソースの場合は重要。
ResharperMbUnitに対応してくれてなかったのでS2Dao.netのテストがしずらかったので
放置していたのが一番まずかったのか。


昔のシステムをどうするかはまた別の問題。。。