하이버네이트 VS iBatis 성능 비교: 이번에는 select

결과는 비슷하다. 차이 없다.

어제는 insert 성능 비교했었는데, 단일 insert 문이야 얼마나 차이가 나겠냐. 고작 3~4 밀리세컨 가지고 성능을 논하기는 뭐할 것 같아서, 1000건~5000건을 한꺼번에 insert 시키는 시간을 측정해 봤더니, 이건 뭐 하이버네이트가 한 5~6배는 빠르게 나왔었다. 코드까지 열어봐도 잘 모르겠지만, 배치 업데이트를 하는것처럼 보인다. 그러지 않고서는 저렇게 성능차이가 날 수 없다. 아니면 내가 뭔가 잘못 테스트 했거나….

코드는 github에 올려두었으니, 해보고 싶으신 분들은 직접 해보시면 됩니다.

https://github.com/keesun/his

어제 저녁에는 select 성능을 측정하다가 퇴근시간이 다되서 나갔는데, 오늘 오전에 마저 해봤더니, 성능이 비슷하게 나왔습니다. 예상했던 결과입니다. 하이버네이트나, iBatis나 결국은 DataSource 빈 통해서 가져오는거고, 그 위에서 맵핑좀 하고, 미리 만들어둔 쿼리 가져다가 쓰는것 뿐이니까요.

소스 코드에서는 MemberServiceIntegTest 클래스를 실행해보시면 됩니다.

하이버네이트와 아이바티스 DAO를 사용하는 서비스 구현체를 가지고 테스트했습니다. 처음엔 DAO를 직접 가져다가 테스트 했는데, 그때는 테스트 클래스 위에 붙인 @Transacional 때문에, 트랜잭션 단위가  테스트 메서드로 묶이는데, 그게 성능에 영향을 준건지, Hibernate가 iBatis보다 select 성능이 2배 정도 높게 측정됐었습니다. 조금 차이는건 이해하겠지만, 2배 정도 차이나는건 이해할 수가 없고, 원인도 모르겠더군요. 그러던 중 직장 동료분께서 트랜잭션 범위에 대해서 조언을 주셨고, 결국 서비스를 구현하여, 서비스 구현체에 @Transional을 붙인 상태로 테스트 해보게 됐습니다.

테스트 코드 찾기 귀찮으신 분들을 위해서…

[java]
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/testContext.xml")
public class MemberServiceIntegTest {
   
    @Autowired MemberServiceHibernateImpl memberServiceHibernate;
    @Autowired MemberServiceIbatisImpl memberServiceIbatis;

    @Before
    public void setUp(){
        memberServiceHibernate.flushAndClear();
        memberServiceIbatis.deleteAll();
    }

    @Test
    @Repeat(10)
    public void hibernate(){
        //GIVEN
        List<Member> member5000 = MemberTestUtils.makeMember5000();
        for(Member newMember : member5000) {
            memberServiceHibernate.add(newMember);
        }
        memberServiceHibernate.flushAndClear();
        System.out.println("Hibernate: insert 5000 complete!");

        //WHEN
        StopWatch watch = new StopWatch();
        watch.start();
        for(int i = 0 ; i < 100 ; i++) {
            List<Member> members = memberServiceHibernate.list();
        }
        memberServiceHibernate.flushAndClear();
        watch.stop();

        //THEN
        System.out.println(watch.prettyPrint());
    }

    @Test
    @Repeat(10)
    public void iBatis(){
        //GIVEN
        List<Member> member5000 = MemberTestUtils.makeMember5000();
        for(Member newMember : member5000) {
            memberServiceIbatis.add(newMember);
        }
        System.out.println("iBatis: insert 5000 complete!");

        //WHEN
        StopWatch watch = new StopWatch();
        watch.start();
        for(int i = 0 ; i < 100 ; i++) {
            List<Member> members = memberServiceIbatis.list();
        }
        watch.stop();
        //THEN
        System.out.println(watch.prettyPrint());
    }

}
[/java]

5천 건을 넣고, selecrt를 100번한 시간을 측정하는 겁니다. 그렇게 하이버 10번, iBatis 10번. 해본 결과는 다음과 같습니다.

Hibernate: insert 5000 complete!
StopWatch ”: running time (millis) = 6428
—————————————–
ms     %     Task name
—————————————–
06428  100% 

Hibernate: insert 5000 complete!
StopWatch ”: running time (millis) = 5399
—————————————–
ms     %     Task name
—————————————–
05399  100% 

Hibernate: insert 5000 complete!
StopWatch ”: running time (millis) = 3758
—————————————–
ms     %     Task name
—————————————–
03758  100% 

Hibernate: insert 5000 complete!
StopWatch ”: running time (millis) = 3773
—————————————–
ms     %     Task name
—————————————–
03773  100% 

Hibernate: insert 5000 complete!
StopWatch ”: running time (millis) = 3741
—————————————–
ms     %     Task name
—————————————–
03741  100% 

Hibernate: insert 5000 complete!
StopWatch ”: running time (millis) = 3735
—————————————–
ms     %     Task name
—————————————–
03735  100% 

Hibernate: insert 5000 complete!
StopWatch ”: running time (millis) = 3719
—————————————–
ms     %     Task name
—————————————–
03719  100% 

Hibernate: insert 5000 complete!
StopWatch ”: running time (millis) = 4156
—————————————–
ms     %     Task name
—————————————–
04156  100% 

Hibernate: insert 5000 complete!
StopWatch ”: running time (millis) = 3829
—————————————–
ms     %     Task name
—————————————–
03829  100% 

Hibernate: insert 5000 complete!
StopWatch ”: running time (millis) = 3785
—————————————–
ms     %     Task name
—————————————–
03785  100% 

iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 3753
—————————————–
ms     %     Task name
—————————————–
03753  100% 

iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 3568
—————————————–
ms     %     Task name
—————————————–
03568  100% 

iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 3521
—————————————–
ms     %     Task name
—————————————–
03521  100% 

iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 3558
—————————————–
ms     %     Task name
—————————————–
03558  100% 

iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 3471
—————————————–
ms     %     Task name
—————————————–
03471  100% 

iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 3497
—————————————–
ms     %     Task name
—————————————–
03497  100% 

iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 3667
—————————————–
ms     %     Task name
—————————————–
03667  100% 

iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 3460
—————————————–
ms     %     Task name
—————————————–
03460  100% 

iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 3524
—————————————–
ms     %     Task name
—————————————–
03524  100% 

iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 3467
—————————————–
ms     %     Task name
—————————————–
03467  100%

4 thoughts on “하이버네이트 VS iBatis 성능 비교: 이번에는 select”

  1. 단일테이블에 대한 select에는 큰 차이가 없을것같은 생각이 드네요. join 과 group by를 동시에 사용해야하는 sql를 테스트해보시면 어떨지요?
    member 리스트를 취득하면서 member클래스안에는 주소리스트를 동시에 가져오는등..

    1. 넵 해보고 싶은데요. 시나리오를 어떻게 해야될까요?

      Member가 가지고 있는 모든 Address도 Member를 select할 때 전부 select 하게 할까요?

      아니면 Member 객체만 가져온 다음에 나중에 Address List에 접근했을 때, Address를 순차적으로 가져오게 할까요?

      아니면 방금과 비슷하지만, 순차적으로 가져오지 말고, List 중에서 20건씩 뭉탱이로 가져오게 할까요?

      흠.. 일단은 맨 위에 적은 방법을 시도해보겠습니다.

  2. 캐시를 하느냐 안하느냐에 따라서 select는 성능차이가 많이 날 것 같더라고요. 최근에 MyBatis는 자체 캐시 말고도 서드파티 캐시(memcached 같은)를 연결해서 사용도 가능하더라고요.

    1. 넹. 그러게요. 캐시까지 끼기 시작하면 시나리오는 곱하기가 되는거고. 이렇게 단편적인 성능 테스트는 무의미한것 같아요.

Leave a Reply

Your email address will not be published. Required fields are marked *