-- L6 (b) child scalar IN projection — SELECT new carrier(h.feedItem.id, h.color, h.text, h.createdAt)
-- FeedProjectionIT.l6ExplainProjectionHasLimitAndSemiJoinNotNarrowerWidth (seed 100, page size 20)
-- SELECT h.feed_item_id, h.color, h.text, h.created_at FROM highlights h
--   WHERE h.feed_item_id IN (SELECT fi.id FROM feed_items fi ORDER BY fi.first_highlighted_at DESC, fi.id ASC LIMIT 20)
-- 읽기 포인트: Hash Semi Join 이라 자식 행(1509)만 반환 — 부모 M × 자식 K 로 곱하지 않는다(카테시안 없음).
--            L5 배치 IN (b)와 같은 shape/행수(1509). 프로젝션은 필요 컬럼만(color/text/created_at) 읽는다.

Hash Semi Join  (cost=50.51..235.83 rows=177 width=686) (actual time=0.218..0.452 rows=1509 loops=1)
  Hash Cond: (h.feed_item_id = "ANY_subquery".id)
  Buffers: shared hit=202
  ->  Seq Scan on highlights h  (cost=0.00..178.71 rows=1771 width=686) (actual time=0.148..0.226 rows=1961 loops=1)
        Buffers: shared hit=161
  ->  Hash  (cost=50.26..50.26 rows=20 width=16) (actual time=0.067..0.067 rows=20 loops=1)
        Buckets: 1024  Batches: 1  Memory Usage: 9kB
        Buffers: shared hit=41
        ->  Subquery Scan on "ANY_subquery"  (cost=50.01..50.26 rows=20 width=16) (actual time=0.060..0.062 rows=20 loops=1)
              Buffers: shared hit=41
              ->  Limit  (cost=50.01..50.06 rows=20 width=24) (actual time=0.059..0.060 rows=20 loops=1)
                    Buffers: shared hit=41
                    ->  Sort  (cost=50.01..50.62 rows=246 width=24) (actual time=0.059..0.059 rows=20 loops=1)
                          Sort Key: fi.first_highlighted_at DESC, fi.id
                          Sort Method: top-N heapsort  Memory: 26kB
                          Buffers: shared hit=41
                          ->  Seq Scan on feed_items fi  (cost=0.00..43.46 rows=246 width=24) (actual time=0.035..0.041 rows=100 loops=1)
                                Buffers: shared hit=41
Planning Time: 0.064 ms
Execution Time: 0.497 ms
