Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Info

JPA는 SQL문을 통해 어플리케이션을 작성했을때보다, 수많은 귀찮은 일을 하지 않아도된다는것을

실습을 통해 파악을 하였습니다. 하지만 실제 그것이 어떠한 SQL문을 수행하는지

또한 그 SQL문이 성능적으로 문제가 없는지 데이터베이스를 병행해서 공부해야하는 과제가 있습니다.

여기서는 다소 자연스럽지 못하더라도 데이터베이스를 공부했을때 일반적인 사항과 JPA의 내용과 엮어보겠습니다.

...

Table of Contents

실행계획 팁보기

관계형 데이터베이스의 종류는 많으며, SQL문을 빠르게 작동시키기위해 실행계획을 세우게 되며

이것은 각각의 데이터베이스마다 다르며 데이터베이스마다  풀스캔/인덱스스캔등의 차이에따라도 차이에 따라서도 다른 실행계획이 나옵니다.또한 DB가 IO장치를 어떻게 활용할것인가? 까지 포함하면 더욱더 상이하고 복잡한 실행계획이 수행됩니다. 

SQL문에서 이러한 실행계획을 조정할수 없을뿐더러, 전적으로 DataBase에게 위임하게 됩니다. 

...

실행이 되고 실제 데이터베이스에서 실행계획이 어떻게 되는지 점검할 필요가 있습니다.

...


JPA문이  실제 어떠한 SQL문을 실행할지 예측할수도 있지만, 아래 옵션을 켜서 실제 SQL문 확인가능합니다.

  • spring.jpa.properties.hibernate.show_sql=true
  • spring.jpa.properties.hibernate.use_sql_comments=true
  • spring.jpa.properties.hibernate.format_sql=true

...

이것은 유닛테스트 작성에 시간을 줄여,  SQL/SP에는 도저히 코드변경점이 많아 시도해볼수 없는

많을것들을 할수 있게하며, 궁극적으로 어플리케이션이 어플리케이션에서 DB 호출 최적화를 할수 있는 기회를 여유시간을 가질수가 있습니다.

대부분의 성능문제는 쿼리 자체 최적화문제가 아닌, 어플리케이션이 불필요하게  많은 쿼리를 호출하는데 발생합니다.

물론 실행계획까지 개발툴에 통합되어 포함되었으면 하는 바램도 있습니다. 




실행계획 조사하기

번거롭지만, JPA를 학습하고 사용하는동안, JPA사용을 통해 단축된 개발시간을 이러한 습관을 가지는 시간을

확보하는것이  중요해보입니다.

JOIN에 따른 성능 측정

이것을 정리한 다시 이유는, JOIN및 조건절에 따라 드라이븐이 시작되는 위치가 달라질수도 있고

절차형 프로그래밍에서 이야기하는 루프의 형태가 달라질수 있다란 의미입니다.

스캔 범위/방식에따른 실행계획 전략

성능을 위한 스캔 전략은 3가지정도로 요약할수 대표적인 스캔 타잎은 3가지로 분류할수 있습니다.

  • 이중루프(Nested Loops) : 한쪽테이블을 읽으면서 결합조건에 맞는 레코드를 다른쪽에서 찾음
  • Sort Merge : 결합할 두 테이블을 정렬을 하고 순차적으로 결합
  • Hash : 결합 키값을 해시로 맵핑, 엑세스 횟수를 줄이고 약간비용이드는 랜덤 접근

스캔범위및 실행 계획이 복잡해지지 않게 하기 위해서 말은쉽지만 어려운 방법 두가지입니다.

  • 스캔 범위 줄이기
  • 조인을 덜 복잡하게 만들기

참고 : https://community.modeanalytics.com/sql/tutorial/sql-performance-tuning/


루프중에도 양쪽풀스캔을(A X B) 랜덤스캔 방식으로 이중루프중에도 양쪽풀스캔을(곱하기)하고 랜덤스캔을 하는 케이스가 성능적으로 가장 나쁜 케이스라고 보시면됩니다보시면되며

조인이 복잡하면 절차형 프로그래밍에서 이야기하는 루프의 형태를 예측하기가 어렵습니다.


조건이 잘못되거나,필터(파티션)를 고려하지 않거나, 인덱스설정에따라 조인의 실행계획은 최악이 될수가 있습니다

참조해야할 테이블수가 늘어남에따라 조인의 복잡도를 감소시켜, 우리가 원하는 집합을 만들기란 어려운일중의 하나이며

특히나 쿼리문만보고 실행계획을 예측한다란것은 거의 불가능에 가깝습니다.

권한 이양의 죄악

이러한 실행계획 개입은, SQL문을 통해 할수있는게 아니고, RDB에 모든것을 이양해야하고

실제 작동을 시켜 실행계획을 파악해야합니다파악해야한다는것입니다. 테이블 설계가 동일하다고 가정했을시

코드가 길어도 실행계획이 띄어난 SQL문 VS 간결한 SQL문, 두가지 SQL문이 있다고 하면

전자를 만들수 있는 SQL개발자가 더 뛰어난 개발자로 분류하였습니다.

실행계획이 띄어난 SQL문을 생성하기위해 RDB가 숨기고 있는 내부절차를 깊숙히 파악해야하며

몇가지 일반적으로 최악이 아닌 일반화는 있지만, 표준화가 되기 어려운내용입니다.

JPA의 경우도 이러한 권한을 받을수가 없습니다. 다만  최악의 실행계획을 수행하는 코드를 일반적으로 생성하지 않습니다.

대부분의 경우 JPA의 기본 인테페이스가 이해하는 SQL문이, 우리가 이해하는 SQL문보다 성능적으로 나쁘지 않는 SQL문을 만들어내며

테이블도 자동으로 생성해줄수 있습니다. 하지만 이것만으로 충분하지 않습니다.

JPA 는 SQL문이 하지못하는 몇가지 성능에 관련된 전략을 사용할수가 있습니다.

같은 쿼리라도 달라지는 RDB에의해 변경이되는 복잡한 실행계획에만 의존하지 않겠다는 전략입니다.

하지만 시간이흘러 다음 데이터베이스에서는 어떠한 SQL문의 실행계획이 뛰어날지 혹은?

데이터량이 늘어나는순간 실행계획이 바뀌게 될지 예측하기가 어렵습니다.

일반적으로 실행계획에 최악이 아닌 방식을 택할수 있지만, 항상 최선인 방식을 택하고 또한

그것이 성능적으로 뛰어난 SQL문이라고 가이드 라인으로 채택하기도 어렵습니다.

JAP를 통한 튜닝 포인트의 변화

JPA에서는 실행계획이 틀어지고, 예측하기 어려운 튜닝포인트를 쿼리중심에서

OOP중심적으로 해결시도를 하고있으며 ,

JPA PROXY/영속성 전이등을 사용하여, 어플리케이션 자체에서 DB접근을 최소화하는

전략을 택하게 됩니다.


Read전략:

  • 즉시읽기( Eager loading) : 
  • 지연읽기 ( Lazy loading ) :

...

  • ALL : 부모의 변화가 자식에게 모두 전가
  • PERSIST : 부모의 영속화 될때 자식도 영속화가됨
  • MERGE : 트랜젝션이 종료되고 변경사항이 merge()수행시 변경사항적용
  • REMOVE : 부모삭제시 연관된 자식도 삭제
  • REFRESH : 부모가 변경되면 자식도 변경
  • DETACH : 부모가 DETACH되면, 연관된 ENTITY도 DEATCH되어 변경반영 죽시 안됨
  • orphanRemoval : 연관관계가 끊어진 자식을 자동으로 제거

위 전략은 모두, 어플리케이션에서 DB와 연관된 불필요한 Read/Write등을 줄이고 그것을 어플리케이션에

반영할수 있는 기회를 제공해줍니다. 이것은 케이스별로 사용해야할 전략이 다르기 때문에

구체적인 예와함께 다시 언급을 하고, 현재는 이러한게 있는것만 알고 넘어가겠습니다. 참고: http://zzong.net/post/15