지난 번 insert 성능 테스트를 했을 때는 Hibernate가 5~6배 빠르게 나왔다. 그 때 테스트의 문제는 하이버네이트의 Flush()와 관련이 많다. 자세히 설명하기는 피곤하니 그냥 생략하겠다. flush(), Write Behind 등으로 검색하면 관련 자료를 많이 찾아볼 수 있으니 직접 찾아보자.

결론부터 말하자면, 비슷하거나 iBatis가 아주 조금 빠르다 또는 테스트하기 어렵다.

SQL 한 건의 성능을 비교하는게 참 애매하다. 한 건 실행해봤자 어떨 때는 1ms도 안 걸릴 때가 많다. 게다가 하이버네이트는 Write Behind를 사용하기 때문에 더 어렵다. 명식적으로 flush()를 하면 결국에 iBatis보다 느릴 수밖에 없다. 하는 일이 많은데 어쩌랴… JDBC와 Hibernate를 혼용하는 메서드가 아니라면, 실제 업무에서 flush()를 사용할 일은 거의 없다. 하이버네이트가 알아서 필요할 시기에 SQL이 flush 되도록 경우가 대부분이다.

JDBC나 iBatis와 Hibernate를 혼용하는 경우라면, 네이티브 쿼리나 배치 작업일 가능성이 높은데, 네이티브나 배치 작업의 비율이 많다면 하이버네이트 보다는 Spring JDBC나 iBatis로 하는게 좋다.

아무튼, 다시 테스트한 코드를 보자.
[java]
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/testContext.xml")
public class InsertPerformanceTest {

    @Autowired MemberServiceHibernateImpl memberServiceHibernate;
    @Autowired MemberServiceIbatisImpl memberServiceIbatis;

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

    @Test
    @Repeat(20)
    public void iBatis(){
        StopWatch stopWatch = new StopWatch();
        List<Member> member5000 = MemberTestUtils.makeMember5000();
        for(Member newMember : member5000) {
            stopWatch.start();
            memberServiceIbatis.add(newMember);
            stopWatch.stop();
        }
        System.out.println("iBatis: insert 5000 complete!");
        System.out.println(stopWatch.shortSummary());
    }

    @Test
    @Repeat(20)
    public void hiebrnate(){
        StopWatch stopWatch = new StopWatch();
        List<Member> member5000 = MemberTestUtils.makeMember5000();
        for(Member newMember : member5000) {
            stopWatch.start();
            memberServiceHibernate.add(newMember);
//            memberServiceHibernate.flushAndClear();
            stopWatch.stop();
        }
        System.out.println("Hiebrnate: insert 5000 complete!");
        System.out.println(stopWatch.shortSummary());
    }

}
[/java]

이번에도 서비스 코드 가지고 테스트를 해봤다. 5천건을 넣으면서 얼마나 걸렸는지 20번 반복 테스트 해봤다. 결과는 다음과 같다.

iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 1944
iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 1241
iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 1047
iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 764
iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 496
iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 372
iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 358
iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 352
iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 364
iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 355
iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 532
iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 345
iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 358
iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 377
iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 354
iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 365
iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 362
iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 354
iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 347
iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 373
Hiebrnate: insert 5000 complete!
StopWatch ”: running time (millis) = 1093
Hiebrnate: insert 5000 complete!
StopWatch ”: running time (millis) = 825
Hiebrnate: insert 5000 complete!
StopWatch ”: running time (millis) = 671
Hiebrnate: insert 5000 complete!
StopWatch ”: running time (millis) = 430
Hiebrnate: insert 5000 complete!
StopWatch ”: running time (millis) = 429
Hiebrnate: insert 5000 complete!
StopWatch ”: running time (millis) = 415
Hiebrnate: insert 5000 complete!
StopWatch ”: running time (millis) = 414
Hiebrnate: insert 5000 complete!
StopWatch ”: running time (millis) = 419
Hiebrnate: insert 5000 complete!
StopWatch ”: running time (millis) = 419
Hiebrnate: insert 5000 complete!
StopWatch ”: running time (millis) = 410
Hiebrnate: insert 5000 complete!
StopWatch ”: running time (millis) = 417
Hiebrnate: insert 5000 complete!
StopWatch ”: running time (millis) = 428
Hiebrnate: insert 5000 complete!
StopWatch ”: running time (millis) = 424
Hiebrnate: insert 5000 complete!
StopWatch ”: running time (millis) = 415
Hiebrnate: insert 5000 complete!
StopWatch ”: running time (millis) = 415
Hiebrnate: insert 5000 complete!
StopWatch ”: running time (millis) = 421
Hiebrnate: insert 5000 complete!
StopWatch ”: running time (millis) = 419
Hiebrnate: insert 5000 complete!
StopWatch ”: running time (millis) = 420
Hiebrnate: insert 5000 complete!
StopWatch ”: running time (millis) = 450
Hiebrnate: insert 5000 complete!
StopWatch ”: running time (millis) = 417

Process finished with exit code 0

상세하게 찍어보면 이렇다.
iBatis: insert 5000 complete!
StopWatch ”: running time (millis) = 1958
—————————————–
ms     %     Task name
—————————————–
00003  000% 
00000  000% 
00001  000% 
00001  000% 
00001  000% 
00001  000% 
00001  000% 
00000  000% 
00001  000% 
00001  000% 
00001  000% 
00001  000% 
00001  000% 
00000  000% 
00001  000% 
00000  000% 
00001  000% 
00001  000% 
00000  000% 
00001  000% 
00000  000% 
00001  000% 
00001  000% 
00000  000% 
00001  000% 
00001  000% 
//생략
00000  000% 
00001  000% 
00000  000% 
00001  000% 
00000  000% 

Hiebrnate: insert 5000 complete!
StopWatch ”: running time (millis) = 1685
—————————————–
ms     %     Task name
—————————————–
00014  001% 
00001  000% 
00001  000% 
00000  000% 
00001  000% 
00000  000% 
00000  000% 
00001  000% 
00000  000% 
00001  000% 
00000  000% 
00001  000% 
00000  000% 
00001  000% 
00000  000% 
00001  000% 
00000  000% 
00001  000% 
00000  000% 
00000  000% 
00001  000% 
00000  000% 
//생략
00000  000% 
00001  000% 
00000  000% 

Process finished with exit code 0

자, 이거가지고.. iBatis와 Hibernate의 insert 성능을 논할 수 있겠는가…. 뭐라고 논할 수 있을까? 난 모르겠다. 누군가 하이버네이트의 Flush()에도 영향을 받지 않고 순순히 select 한 건에 대한 성능을 제대로 측정할 수 있는 방법에 대해 제보해 주신다면 그렇게 해보겠지만, 사실 이런 성능 측정은 무의미 하다고 생각한다. 뭐하러.. 이런걸 해보는지 몰겠다. 하두 하이버 성능이 어쩌구 저쩌구 해대고, 사내에서도 성능 측정 해볼 일이 있어서 해봤을 뿐…

이럴 시간에 하이버네이트 써서 후딱 서비스 개발이나 하고, 해당 서비스가 느리면, 그때가서 성능 개선을 해도 늦지 않을 것 아닌가… 겁은 많고, 귀는 얇고, 공부는 안하고 그러면서 뭘 하겠다고.