いろいろベンチ(3)


いろいろリンクされてるようなので,恥を忍んでコードを公開します(とゆうても断片だけど).
#おかしなところがあったら,ご指摘願いまーす.


まず,INSERT.以下のコードをそれぞれ1000回繰り返してかかった時間を計測.

===JDBC===
private void createCats(Connection con, int id) throws Exception {
  PreparedStatement st = con.prepareStatement("INSERT INTO CAT VALUES(?, ?, ?, ?)");
  st.setString(1, ""+id);
  st.setString(2, "princess");
  st.setString(3, "F");
  st.setFloat(4, id);
  st.executeUpdate();
  st.close();
}

===Hibernate===
private void createCats(Session session, int id) throws Exception {
  Cat princess = new Cat();
  princess.setName("princess");
  princess.setSex('F');
  princess.setWeight(id);
  session.save(princess);
}

===Torque===
private void createCats(Connection con, int id) throws Exception {
  Cat princess = new Cat();
  princess.setCatId(""+id);
  princess.setName("princess");
  princess.setSex("F");
  princess.setWeight(id);
  princess.save(con);
}

===DbUtils===
private void createCats(Connection con, int id) throws Exception {
  QueryRunner qr = new QueryRunner();
  qr.update(con, "INSERT INTO CAT VALUES(?, ?, ?, ?)",
            new Object[] { ""+id, "princess", "F", new Float(id) });
}

んで,1000レコードできたんで,それを1000回SELECTする(以下のコードを1000回繰り返す).

===JDBC===
private List selectAllCats(Connection con) throws Exception {
  List list = new ArrayList();
  PreparedStatement st = con.prepareStatement("SELECT * FROM CAT");
  ResultSet rs = st.executeQuery();
  while(rs.next()) {
    Cat cat = new Cat();
    cat.setId(rs.getString(1));
    cat.setName(rs.getString(2));
    cat.setSex(rs.getString(3).charAt(0));
    cat.setWeight(rs.getFloat(4));
    list.add(cat);
  }
  rs.close();
  st.close();
  return list;
}

===Hibernate===
private List selectAllCats(Session session) throws Exception {
  List list = new ArrayList();
  Query query = session.createQuery("select cat from Cat as cat");
  for (Iterator it = query.iterate(); it.hasNext();) {
    Cat cat = (Cat) it.next();
    list.add(cat);
  }
  return list;
}

===Torque===
private List selectAllCats(Connection con) throws Exception {
  return CatPeer.doSelect(new Criteria(), con);
}

===DbUtils===
private List selectAllCats(Connection con) throws Exception {
  ResultSetHandler h = new BeanListHandler(Cat.class);
  QueryRunner run = new QueryRunner();
  List list = (List) run.query(con, "SELECT * FROM CAT", h);
  return list;
}

SELECTで取得した1000個のオブジェクトを以下のように1つ1つUPDATEする.

===JDBC===
private void updateCats(Connection con, List list) throws Exception {
  float f = 0;
  for (Iterator it = list.iterator(); it.hasNext(); ) {
    Cat cat = (Cat)it.next();
    PreparedStatement st;
    st = con.prepareStatement("UPDATE CAT SET NAME=?, sex=?, weight=? WHERE cat_id=?");
    st.setString(1, cat.getName().toUpperCase());
    st.setString(2, "M");
    st.setFloat(3, cat.getWeight() + f++);
    st.setString(4, cat.getId());
    st.executeUpdate();
    st.close();
  }
}

===Hibernate===
private void updateCats(Session session, List list) throws Exception {
  float f = 0.0f;
  for (Iterator it = list.iterator(); it.hasNext(); ) {
    Cat cat = (Cat)it.next();
    cat.setName(cat.getName().toUpperCase());
    cat.setSex('M');
    cat.setWeight(cat.getWeight() + f++);
    session.update(cat);
  }
}

===Torque===
private void updateCats(Connection con, List list) throws Exception {
  for (Iterator it = list.iterator(); it.hasNext(); ) {
    Cat cat = (Cat)it.next();
    cat.setName(cat.getName().toUpperCase());
    cat.setSex("M");
    cat.setWeight(cat.getWeight() + 1.0f);
    cat.save(con);
  }
}

===DbUtils===
private void updateCats(Connection con, List list) throws Exception {
  float f = 0;
  for (Iterator it = list.iterator(); it.hasNext(); ) {
    Cat cat = (Cat)it.next();
    QueryRunner run = new QueryRunner();
    run.update(con, "UPDATE CAT SET NAME=?, sex=?, weight=? WHERE cat_id=?",
                    new Object[] { cat.getName().toUpperCase(), "M",
                                   new Float(cat.getWeight() + f++), cat.getId() });
  }
}

で最後は,この1000個のオブジェクトを,以下のコードで1つ1つDELETEして,おしまい.

===JDBC===
private void deleteCats(Connection con, List list) throws Exception {
  for (Iterator it = list.iterator(); it.hasNext();) {
    Cat cat = (Cat) it.next();
    PreparedStatement st = con.prepareStatement("DELETE FROM CAT WHERE cat_id=?");
    st.setString(1, cat.getId());
    st.executeUpdate();
    st.close();
  }
}

===Hibernate===
private void deleteCats(Session session, List list) throws Exception {
  for (Iterator it = list.iterator(); it.hasNext();) {
    Cat cat = (Cat) it.next();
    session.delete(cat);
  }
}

===Torque===
private void deleteCats(Connection con, List list) throws Exception {
  for (Iterator it = list.iterator(); it.hasNext();) {
    Cat cat = (Cat) it.next();
    CatPeer.doDelete(cat, con);
  }
}

===DbUtils===
private void deleteCats(Connection con, List list) throws Exception {
  for (Iterator it = list.iterator(); it.hasNext();) {
    Cat cat = (Cat)it.next();
    QueryRunner run = new QueryRunner();
    run.update(con, "DELETE FROM CAT WHERE cat_id=?", cat.getId());
  }
}

トランザクションは,INSERT, SELECT, UPDATE, DELETEごとで完結.


テストに使ったのは,HibernateサンプルにあるCatテーブル.Hibernateは,ID生成にuuid.hexを指定してるけど,他はテキトウ.
なんで,ちょっとHibernate不利な設定だったのかもしれない.


あとTorqueの生成方法はよくわかんないんで,Torque-genにあったのを見よう見まねで書き換えて生成.
Hibernateのオプションは,いじってません.せいぜい,

hibernate.cglib.use_reflection_optimizer

をON/OFFしてみたくらいです.


んで,使ったバージョンは,

  • Hibernate2.1
  • Torque3.1
  • DbUtils1.0

でした.


ps.
追いかけては無いんですが,P6Spyでのぞいたところ,なんでかHibernateはINSERT, UPDATE, DELETEは6〜7回しかログに出てなかったんだよね.
#SELECTはちゃんと1000回ログ出てんのに.


ps2.
あと,これも追いかけてないんですが...
#ちゃんとギモンは追求しようよ>おれ.

TorqueやHibernateは,更新するオブジェクトが取得したときと何も変わってないと,UPDATE文を実行したないみたいですが,これは事実なんでしょか?