Versions Compared

Key

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

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

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

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

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

스캔 실행계획

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

이것은 각각의 데이터베이스마다 다르며 풀스캔/인덱스스캔등의 차이에따라도 다른 실행계획이 나옵니다.

또한 IO장치를 어떻게 활용할것인가? 까지 포함하면 더욱더 상이하고 복잡한 실행계획이 수행됩니다. 

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

즉, JPA도 이러한 실행계획에 관여할수 없으며 이러한 실행계획을 확인하는 방법은 SQL문을 실제

실행하여 확인하는것입니다.

이름명령어
Oracleset autotrace traceonly
MSSQLSET SHOWPLAN_TEXT_ON
DB2EXPLAIN ALL WITH SNAPSHOT FOR SQL 구문
PostreSQLEXPAIN SQL 구문
MySQLEXPLAIN EXTENDED SQL 구문


JPA TO SQL

JPASQL

studentList = findByGroupInfoName("학생")

SELECT * FROM user ui left join spring.group_info gi

on gi.group_id = ui.group_id and gi.name="학생"

-- 위구문을 어플리케이션사용하기위해서는 실제는

몇가지 더 변환과정이 필요합니다.

dataset = runsql(..)

javaobj = datasetToObj(result)

jsonobj = objToJson(javaobj)


앞장에서 이미 설명된 컨셉이며, JPA가 SQL에 비해 어플리케이션에서 단순하고 일관성있게 사용하는지

보여주는 예입니다. 반환타잎은 Java오브젝트뿐만아니라,웹에서 바로 사용가능한 Json 결과로 뿌려줄수 있기떄문에

JPA에서는  JPA에서  사용자정보에서 학생정보만 추출하는 과정이 이 한줄이외에 더 추가되는것은 개발 생산성 낭비로

 측정하고 측정하고 있습니다.  하지만 SQL문을 직접 작성하지 않을뿐 이러한 JPA 인터페이스가 어떤 SQL문으로 변환되어

...

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


어플리케이션의 JPA테스트코드와 SQL 실행을 Trace한 예

쿼리실행을 JPA를 통해 간단하게 할수 있기때문에 , 데이터베이스를 조회하고 변경하는 코드에대해

어플리케이션 레벨에서 TestCase 작성을 쉽게하고 실제 작동되는 SQL문도 체크할수 있습니다.

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

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

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

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

Image Added


실행계획 조사하기

해당 SQL문은, 이중루프가 사용됨을 


JOIN 작동방식 정리(부록)

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

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

대표적인 스캔 타잎은 3가지로 분류할수 있습니다.

  • 이중루프(Nested Loops) : 한쪽테이블을 읽으면서 결합조건에 맞는 레코드를 다른쪽에서 찾음
  • Sort Merge : 결합할 두 테이블을 정렬을 하고 순차적으로 결합
  • Hash : 결합 키값을 해시로 맵핑


권한 이양의 죄악

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

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

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

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

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

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

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

하지만 이것만으로 충분하지 않습니다.

JPA에서는 이러한 탐색효율과 반복을 최적화하는 방법에대해서 RDB에게만 모든것을 맡기지 않습니다.

JPA PROXY 라는 중간 객체를 통해 Lazy loading, Eager loading등의 전략을 수행할수가 있습니다. 

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