엔티티만 페이징한 SQL의 실행계획 (b) — Limit 노드 존재 (대조군)
출처: FeedPersistenceIT.l4ExplainCollectionJoinHasNoLimitButEntityPagingDoes 콘솔 출력 (b)
조건: seed(100) 직후. warm buffer cache(shared read=0).
쿼리: EXPLAIN (ANALYZE, BUFFERS)
      SELECT fi.* FROM feed_items fi ORDER BY fi.first_highlighted_at DESC, fi.id ASC LIMIT 20
      (fetch join 없이 엔티티만 페이징한 SQL — DB가 정상적으로 페이징하는 모습)

Limit  (cost=13.42..13.47 rows=20 width=1194) (actual time=0.038..0.040 rows=20 loops=1)
  Buffers: shared hit=11
  ->  Sort  (cost=13.42..13.58 rows=66 width=1194) (actual time=0.038..0.038 rows=20 loops=1)
        Sort Key: first_highlighted_at DESC, id
        Sort Method: top-N heapsort  Memory: 28kB
        Buffers: shared hit=11
        ->  Seq Scan on feed_items fi  (cost=0.00..11.66 rows=66 width=1194) (actual time=0.015..0.019 rows=100 loops=1)
              Buffers: shared hit=11
Planning Time: 0.029 ms
Execution Time: 0.050 ms

관찰(문서 §10):
- 계획 최상단에 Limit 노드가 있고 그 아래 Sort가 top-N heapsort(28kB)로 상위 20행만 취한다 = DB가 페이징을 했다.
  (a) l4-collection-join-no-limit.txt는 Limit 노드가 없어 전체 1961행을 quicksort(445kB)로 정렬했다 — 대조가 요점.
- 28kB(top-N heapsort, 20행) vs 445kB(quicksort, 1961행): "DB 페이징 vs 인메모리 페이징"의 메모리 비용 차이가
  계획 레벨로 드러난다. (a)에 Limit이 없다는 것 자체가 "DB가 페이징을 안 했다 → Hibernate가 메모리에서 했다"의 증거.
- 컬럼명·리터럴 하드코딩이라 인젝션 무관. PG 계획 문구는 버전·통계에 따라 흔들릴 수 있어 강가드 대신 눈 대조로 둔다.
- Buffers: shared read=0 → warm buffer cache. Execution Time 0.050 ms는 executor 내부 시간(§6.4 caveat와 동일).
