« 2011年4月 | トップページ | 2011年6月 »

2011年5月

2011年5月30日 (月)

カルテ表示高速化

開院当初からずっと通院して下さっている,DocumentModel 120件超えの患者さんがいらっしゃるのだが,先日,この患者さんのカルテで SelectAll して検索しようとしたところ,全てのカルテを読み込むのに 20秒以上かかってしまった。
 調べてみたら,RemoteKarteServiceImpl#getDocuments(List ids) で,ModuleModel と SchemaModel を取りに行くために DocumentModel の id ごとに createQuery しており,各 120回以上の createQuery が発生して,かなり時間を食ってしまっていた(em.find は1回 4 msecくらいで終わっているのであまり問題ではなかった)。
 そこで,createQuery をまとめて1回で終わらせて,あとは小細工でフォローしてみたら,大分早くなった。(in のパラメータに List を使うのは増田先生の Twitter で教えてもらいました)
 ちなみに,join fetch も試してみたが,cannot simultaneously fetch multiple bags という exception がでてできなかった。

失敗例
List ret = em.createQuery("from DocumentModel d join fetch d.modules join fetch d.schema where...

DocumentModel 120件超えのカルテで SelectAll で全選択する時間

3回続けて測定した結果

オリジナル方式まとめてクエリ方式
1回目26.771秒4.246秒
2回目21.917秒3.463秒
3回目21.755秒3.183秒

 

ejb/RemoteKarteServiceImpl.java

public List getDocuments(List ids) {
        
  List ret = new ArrayList(3);
        
  // まとめて query
  List mods = em.createQuery("from ModuleModel m where m.document.id in (:ids)")
    .setParameter("ids", ids).getResultList();
  List imgs = em.createQuery("from SchemaModel m where m.document.id in (:ids)")
    .setParameter("ids", ids).getResultList();
        
  // とってきた list を DocumentModel に分配
  for (Long id : ids) {
            
    // DocuentBean を取得する
    DocumentModel document = em.find(DocumentModel.class, id);

    // ModuleBean を取得する
    List modules = new ArrayList();
    for (ModuleModel m : mods) {
      if (m.getDocument().getId() == id) modules.add(m);
    }
    document.setModules(modules);
            
    // SchemaModel を取得する
    List images = new ArrayList();
    for (SchemaModel m : imgs) {
      if (m.getDocument().getId() == id) images.add(m);
    }
    document.setSchema(images);
                        
    ret.add(document);
  }
        
  return ret;
}

« 2011年4月 | トップページ | 2011年6月 »