【Java】iBATISでオブジェクトの配列を持つクラスを利用すると重くなるケースとその回避方法について

2017年7月9日Java, 開発

おはようございます。

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_CDCOMPANY_NAME
00001会社1
00002会社2

従業員テーブル

COMPANY_CDEMP_CDEMP_NAMEAGE
00001000001社員125
00001000002社員233
00001000003社員326
00002000001社員443
00002000002社員530

DTOクラス

Company.java

Emp.java

 

SqlMap

sample.xml

こうすることで、1対多のテーブルに対してもマッピングを行えるが、
会社データを取得した後に、従業員データを会社毎に取得しにいってしまうため
データ量が増えると途端に遅くなってしまう。

処理フローのイメージは次の通り。

  1. 会社データ取得「selectCompanyList」
  2. 会社コード毎に「selectEmpList」を呼び出し、
    Companyクラスの empList に結果をマッピングする

結果的に、従業員数 × 1 (会社データ取得)のSQLが発行されることとなる。
1回のSQLがたとえ 0.0001 秒しか掛からなかったとしても
件数が増えれば増えるほど遅くなるのは明白ですよね。

改善方法

データを一括で取得してから、
結果を iBATIS の GroupBy で指定した列によって
グルーピングするという方法がある。

SqlMap

sample.xml

まとめ

プログラムやシステムにもよるところだと思いますが、
私が経験した感じだと 1/5 から 1/10 くらいの改善がみられました。

最初から遅い遅いとは思いつつ、一つしか方法がないと思い込んでいたのが間違いでした。

もっと早く気づいていればよかった。。

ではでは。

 

スポンサーリンク


関連するコンテンツ

2017年7月9日Java, 開発iBATIS, Java, プログラミング

Posted by doradora