반복되는 User ToOne 부모 쿼리의 실행계획 (N2 — 평탄, 1차 캐시 dedup)
출처: FeedPersistenceIT.l2ExplainRepeatedPageToOneQuery 콘솔 출력
조건: seed(100) 직후. warm buffer cache(shared read=0). id는 시드된 실제 users.id 1건.
쿼리: SELECT * FROM users WHERE id = ?   (@ManyToOne EAGER가 반복하는 2차 SELECT)

Index Scan using pk_users on users
  (cost=0.14..8.15 rows=1 width=2104) (actual time=0.013..0.014 rows=1 loops=1)
  Index Cond: (id = '0a2a85ed-f8f3-47f0-b957-c477f4b077ab'::uuid)
  Buffers: shared hit=2
Planning Time: 0.027 ms
Execution Time: 0.022 ms

주의(문서 §7.3):
- 단건 실행계획은 pages(toone-pages-plan.txt)와 사실상 동일하다: 둘 다 pk Index Scan, ~0.02 ms.
- 그러나 반복 횟수가 다르다. user는 소수 풀(≤20)을 재사용하고 한 번 로드된 대상은 영속성
  컨텍스트(1차 캐시)에 남아 재조회되지 않으므로, 서로 다른 대상(distinct target) 수만큼만
  나간다 → N과 무관하게 ≤20에서 평탄. page는 아이템당 고유라 N번.
- 결론: 같은 @ManyToOne(EAGER)·같은 실행계획인데 곡선이 갈리는 원인은 계획이 아니라
  데이터 분포(카디널리티)다. EXPLAIN만 보면 둘이 똑같아 보이는 것이 '숨은' N+1의 얼굴이다.
