【Java】iBATISでオブジェクトの配列を持つクラスを利用すると重くなるケースとその回避方法について
おはようございます。
Java のシステムでiBATISを利用している場合に、どうにもパフォーマンスが悪いということで調べてみたら
iBATIS を利用した 1対多 のテーブルをマッピングしている箇所がまずかったのがわかりました。。
1対多のテーブルをマッピングするのに、普通にやると多側の取得に N回 のクエリ実行が必要となります。
実はこれがものすごい遅い・・・
スポンサーリンク
iBATISとは
wikiより抜粋
iBATIS は、SQLクエリを POJO (Plain Old Java Object) にマッピングする永続性フレームワークである。SQLクエリはXMLファイルに置くことで一旦アプリケーションと分離される。検索結果のオブジェクトのマッピングは自動的か半自動的に行う。
iBATIS の基本となる考え方は、SQLクエリをXMLファイルに置くことで、関係データベースにアクセスする際に必要となる大量のJavaコードを大幅に減らすことである。
所謂 O/Rマッパーというやつですね。
便利なのですが、使い方を誤ると思わぬデメリットを被る可能性もあります。
サンプル
例えば、
次のようなテーブルを DTO(Data Transfer Object)クラスにマッピングするとした場合。
テーブル
会社テーブル
COMPANY_CD | COMPANY_NAME |
00001 | 会社1 |
00002 | 会社2 |
従業員テーブル
COMPANY_CD | EMP_CD | EMP_NAME | AGE |
00001 | 000001 | 社員1 | 25 |
00001 | 000002 | 社員2 | 33 |
00001 | 000003 | 社員3 | 26 |
00002 | 000001 | 社員4 | 43 |
00002 | 000002 | 社員5 | 30 |
DTOクラス
Company.java
Emp.java
SqlMap
sample.xml
こうすることで、1対多のテーブルに対してもマッピングを行えるが、
会社データを取得した後に、従業員データを会社毎に取得しにいってしまうため
データ量が増えると途端に遅くなってしまう。
処理フローのイメージは次の通り。
- 会社データ取得「selectCompanyList」
- 会社コード毎に「selectEmpList」を呼び出し、
Companyクラスの empList に結果をマッピングする
結果的に、従業員数 × 1 (会社データ取得)のSQLが発行されることとなる。
1回のSQLがたとえ 0.0001 秒しか掛からなかったとしても
件数が増えれば増えるほど遅くなるのは明白ですよね。
改善方法
データを一括で取得してから、
結果を iBATIS の GroupBy で指定した列によって
グルーピングするという方法がある。
SqlMap
sample.xml
まとめ
プログラムやシステムにもよるところだと思いますが、
私が経験した感じだと 1/5 から 1/10 くらいの改善がみられました。
最初から遅い遅いとは思いつつ、一つしか方法がないと思い込んでいたのが間違いでした。
もっと早く気づいていればよかった。。
ではでは。
ディスカッション
コメント一覧
まだ、コメントがありません