1.8 KiB
1.8 KiB
측정값 — 직접 측정
초기화 컬렉션 수와 총 PreparedStatement는 Hibernate Statistics, 지연은 System.nanoTime으로 읽은 값이다.
:::table id="direct-measurement" caption="N별 초기화 컬렉션 수와 총 PreparedStatement" rowHeaderColumn="1"
| N | 초기화 Highlight 컬렉션 | 총 PreparedStatement | 지연 중앙값 |
|---|---|---|---|
| 10 | 10 | 25 | 32.8 ms |
| 100 | 100 | 222 | 85.9 ms |
| 1,000 | 1,000 | 2,022 | 193.7 ms |
:::
조회량은 N에 정확히 비례했다. 여기서 N은 전체 테이블 크기가 아니라 한 요청이 반환한 FeedItem 수다.
문제가 된 조회
@Query("select fi from FeedItem fi where fi.visibility = :visibility")
Page<FeedItem> loadFeed(@Param("visibility") Visibility visibility, Pageable pageable);
:::note
같은 @ManyToOne(EAGER)라도 실행 횟수는 Persistence Context 안의 distinct 대상 수가 정한다. 애너테이션 하나로 갈리지 않는다.
:::
확인한 실행 계획
:::evidence key="feed-explain-plan" alt="Index Scan 뒤 rows=500이 찍힌 EXPLAIN 출력" caption="반복되는 자식 조회의 실행 계획" zoom="true" :::
측정의 범위와 한계
:::warning
지연 값은 이미 열린 테스트 트랜잭션 안에서 어댑터 호출만 잰 단일 스레드·warm-cache 로컬 비교값이다. HTTP 종단 지연도 운영 p99도 아니다.
:::
Hibernate Statistics가 주는 값은 획득한 PreparedStatement 수이지 SQL shape별 실행 횟수가 아니다. shape별 횟수를 원문 SQL 수준에서 확정하려면 다음 중 하나로 따로 수집해야 한다.
- SQL 로그 또는
StatementInspector - datasource-proxy 또는 p6spy
- PostgreSQL statement logging