Files
document-haness/docs/n+1liner/tech-log-studio/jpa-feed-query-performance/decision/decision-read-projection-for-screen-query.md
T

2.9 KiB

id, kind, slug, title, topic, project, status, studio, decisionStatus
id kind slug title topic project status studio decisionStatus
30a37f34-b406-4061-b924-e22e0be0c3bf PROJECT_DECISION read-projection-for-screen-query 화면 조회는 Read Projection을 사용한다 JPA 피드 조회 성능 Liner N + 1문제 게시 전 https://hyeonworks.com/studio/documents/30a37f34-b406-4061-b924-e22e0be0c3bf/edit PROPOSED

화면 조회는 Read Projection을 사용한다

화면에 내보내는 조회는 엔티티를 하이드레이트하지 않고 필요한 스칼라 값만 캐리어로 받는다. 엔티티 그래프 조회는 쓰기 경로에 남기고 읽기 경로는 프로젝션으로 분리한다.

근거

  • Projection 이후에도 1,509행을 읽은 Row Over-fetch 프로젝션의 효과와 남은 비용을 확인한 기록이다.
  • Fetch Join · Batch · Projection 선택 기준 배치와 프로젝션이 서로 다른 비용을 줄인다는 기준이다.
  • Query Strategy는 FeedQueryPort 뒤에서 소유한다 이 구현을 감춘 경계다.

결정문

화면 조회 경로에서는 필요한 컬럼만 선택해 캐리어 record로 받는다. 영속 엔티티를 만들지 않는다.

부모와 자식을 각각 스칼라로 조회하고 애플리케이션에서 조립한다. 이 구현은 조회 포트 뒤에 둔다.

판단 이유

배치를 적용한 뒤에도 엔티티는 통째로 하이드레이트됐다. 페이지 20건을 조회하는데 부모와 연관을 합해 천 개가 넘는 영속 객체가 올라왔다. 화면에는 일부 컬럼만 필요했다.

캐리어 생성자 표현식은 영속 엔티티 대신 스칼라 값으로 record를 만든다. 1차 캐시, 더티체킹, 지연 프록시가 생기지 않는다. 컬럼을 읽기 위한 조인이 있어도 그 대상 엔티티를 만들지 않는다.

측정에서 하이드레이트한 엔티티가 0이 됐고 발행 쿼리도 데이터 규모와 관계없이 두 개로 고정됐다. 부모 스칼라 쿼리와 자식 IN 쿼리다.

이 효과는 배치 설정 여부와 무관하게 성립한다. 배치는 왕복을 줄이고 프로젝션은 적재를 없앤다. 두 전략은 서로를 대신하지 않는다.

영향

  • 반환 형태가 화면 요구에 묶인다. 화면이 바뀌면 캐리어와 쿼리도 바뀐다.
  • 여러 컬렉션을 담는 응답은 생성자 표현식 한 번으로 만들 수 없다. 부모와 자식을 따로 조회해 조립해야 한다.
  • 프로젝션의 이득은 실행계획에서 확인되지 않는다. 필요한 컬럼만 골라도 계획의 행폭 추정치는 오히려 넓어질 수 있다. 엔티티 로드 수로 확인해야 한다.
  • 자식 조회의 행수는 프로젝션이 줄이지 않는다. 부모당 상한이 필요하면 별도 SQL 형태로 풀어야 한다.
  • 읽기 경로와 쓰기 경로의 모델이 갈린다. 같은 저장소를 쓰더라도 조회 전용 계약이 하나 늘어난다.